//#define exUSBMSDC
#include "includes_fw.h"
#include "lib_retina.h"
//#include "config_fw.h" //already in includes_fw.h

#include "mmpf_usbvend.h"
#include "mmpf_usbextrn.h"
#include "mmpf_usbdescr.h"
#include "mmpf_usbuvc.h"
#include "mmpf_usbcolor.h"
#include "mmpf_usbxu.h"
//#include "mmpf_usbpccam.h" //already in mmpf_usbuvc.h
//#include "mmp_err.h"  //already in includes_fw.h
#include "mmpf_rawproc.h"
#include "mmp_reg_jpeg.h"
#include "mmp_reg_scaler.h"
#include "mmp_reg_vif.h"
#include "mmp_reg_ibc.h"
#include "mmp_reg_gbl.h"
#include "mmp_reg_usb.h"

#include "mmp_reg_dma.h"
//#include "mmpf_dma.h" //already in mmpf_usbuvc.h
#include "mmpf_sif.h"
#include "mmpf_sf.h"
#include "mmpf_vif.h"

//#include "sensor_ctl.h"
//#include "3A_ctl.h"
#include "mmps_3gprecd.h"
#include "mmpd_sensor.h"
#include "mmpd_system.h"
#include "mmpf_system.h"
#include "mmpf_timer.h"
//#include "preview_ctl.h"
#include "text_ctl.h"
#include "isp_if.h"
#include "hdm_ctl.h"
#include "mmpf_sensor.h"
#include "mmpf_3gpmgr.h"
//#include "mmpf_dma.h"//already in mmpf_usbuvc.h
//#include "mmp_reg_h264enc.h"
#include "mmpf_mp4venc.h"
#include "mmpf_h264enc.h"
//#include "mmpf_scaler.h"
#include "flash_ctl.h"

#include "motion_dtc.h"

#if (SUPPORT_UVC_FUNC==1)

#include "pcam_usb.h"
#include "pcam_msg.h"
#include "pcam_handler.h"
#if SKYPE_UVC_H264
//#include "mmpf_usb_h264.h"//already in mmpf_usbuvc.h
#include "mmpf_usbuvch264.h"
#endif

#if CUSTOMER == ASU
MMP_UBYTE m_tTAEEnableCount = 0;
#endif

#ifdef ZDW_BARCODE
//#include "kbarimg.h"
//extern MMP_BOOL bPowerOnWorking;
#endif

//#if (/*USB_FRAMEBASE_H264_ONLY + */USB_FRAMEBASE_H264_YUY2_STREAM + USB_FRAMEBASE_H264_MJPEG_STREAM + USB_FRAMEBASE_DUAL_H264_STREAM) > 1
//#error Due to current XU protocol, only 1 of these format could be supported.
//#endif

#if UVC_MOVE_DMA_EN && (UVC_DMA_3K_NUM != 1)
#error UVC_DMA_3K_NUM must == 1 while UVC_MOVE_DMA_EN is on
#endif

#if XU_FRAMEBASE_CAPTURE
FRAMEBASE_CAPTURE gFramebaseCap;
#endif

void usb_vc_cfg_video_probe(MMP_UBYTE format_idx, MMP_UBYTE frame_idx, MMP_ULONG max_frame_size,
                            MMP_ULONG max_payload_size);
void USB_PUT_FIFO_DATA(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit, MMP_UBYTE *data);
void USB_PUT_FIFO(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit, MMP_ULONG data, MMP_ULONG data1);
//void usb_vc_cmd_cfg(MMP_UBYTE req,VC_CMD_CFG *cfg,MMP_ULONG cur_val);

#if SKYPE_MODE_B || USB_MJPEGH264_STREAM
static RES_TYPE_LIST skype_yuy2_to_pcam(MMP_UBYTE skype_res_index);
static PCAM_USB_VIDEO_RES skype_h264_to_pcam(MMP_UBYTE skype_res_index);
#endif

extern MMP_UBYTE  gbCurrentSensor;
extern MMPF_SENSOR_FUNCTION *gsSensorFunction ;

extern ISP_UINT32 gTextColorFormat;
extern ISP_UINT32 gTextPreviewBufAddr;
extern ISP_UINT32 gTextPreviewWidth ;

extern MMP_ULONG glCPUFreq;
extern MMPF_OS_FLAGID   SYS_Flag_Hif;

extern MMP_USHORT USBEP0TxCnt;
extern MMP_UBYTE  USBOutData;

extern MMP_USHORT  UVCTxFIFOSize ;// EP2TxFIFOSize;

//const MMP_UBYTE gbVCITID = 0x01;
#define gbVCITID UVC_IT_ID
//const MMP_UBYTE gbVCOTID = 0x04;
#define gbVCOTID UVC_OT_ID
//const MMP_UBYTE gbVCPUID = 0x03;
#define gbVCPUID UVC_PU_ID

//const MMP_UBYTE gbVCEU0ID = 0x05;
#if SKYPE_UVC_H264  // ID1->ID3->ID5->ID6->ID2->ID4
#define gbVCEU0ID UVC_EU0_ID
#else            //  ID1->ID3->ID6->ID2->ID4
#endif

//const MMP_UBYTE gbVCEU2ID = 0x02; // for AMB cmd
#define gbVCEU2ID UVC_EU2_ID// for AMB cmd
//const MMP_UBYTE gbVCEU1ID = 0x06; // for AIT tool
#define gbVCEU1ID UVC_EU1_ID// for AIT tool

#if SKYPE_UVC_H264
//const MMP_UBYTE gbVCEU3ID = 0x08; // for USB-IF UVC H.264 payload
#define gbVCEU3ID UVC_EU3_ID// for USB-IF UVC H.264 payload
#endif

//const MMP_UBYTE gbVCVCIF = 0x00;// same with descriptor
//#define gbVCVCIF UVC_CTL_IF_NO//0// same with descriptor
//const MMP_UBYTE gbVCVSIF = 0x01;// same with descriptor
//#define gbVCVSIF UVC_STREAM_IF1_NO//1// same with descriptor


MMP_UBYTE  gbVCERRCode;
MMP_UBYTE  gbCurFormatIndex = 1, gbCurFrameIndex = 1;
MMP_UBYTE  gbCurStillFormatIndex = 1, gbCurStillFrameIndex = 1;//,framemode
#if USING_OLD_H264_FILTER
#if SKYPE_H264_TEST
MMP_UBYTE  gbEnableH264Mode = 2;  // VGA 
#else
MMP_UBYTE  gbEnableH264Mode = 1;  // HD
#endif
#else
MMP_UBYTE  gbEnableH264Mode = 0;
#endif

MMP_BOOL    gbAutoFocus;
MMP_UBYTE   gbBandFilter;
MMP_UBYTE   gbTemperInfo;
MMP_UBYTE   gbEVInfo;
MMP_UBYTE   gbGainInfo;
MMP_UBYTE   gbAWB = AWB_DEF;
MMP_UBYTE   gblastAWB;
MMP_UBYTE   gbAE = AEC_DEF;
MMP_UBYTE   gblastAE;
MMP_UBYTE   gbUpdAE;
MMP_UBYTE   gbUpdAWB;
MMP_UBYTE   gbUpdAG;
MMP_UBYTE   gbTriOP;

MMP_USHORT  gsAFocus;
MMP_USHORT  gsZoom;
MMP_USHORT  gsBacklight;
MMP_USHORT  gsTemper;
MMP_USHORT  gsSaturation;
MMP_USHORT  gsContrast;
MMP_USHORT  gsBrightness;
MMP_ULONG   gsEV;
MMP_SHORT   gsHue;
MMP_SHORT   gsGamma;
MMP_SHORT   gsSharpness;
MMP_USHORT  gsGain;

MMP_LONG    glPan,glTilt  ;

__align(2) VIDEO_PROBE       vp =
{
0x0001, // bmHint
0x00,   // bFormatIndex 
0x00,   // bFrameIndex
0x00051615, // dwInterval
0x0000, // wKeyFrameRate
0x0000, // wPFrameRate
0x0000, // wCompQuality
0x0000, // wCompWinSize
0x0000, // wDelay
0x00000000, // dwMaxFrameSize
0x00000000, // dwMaxPayloadSize
} ;

__align(2) VIDEO_PROBE       vpin;
__align(2) STILL_PROBE       sp;    //still probe
__align(2) STILL_PROBE        spin; //still probe in
__align(2) STILL_PROBE        sc;   //still commit
//__align(2) STILL_PROBE          scin; //still commit in

//MMP_UBYTE   gbstistart;
MMP_UBYTE   gbUvcCommitted;

//#ifdef UVC_TEST


//The info needed for UVC sample
typedef struct _UVC_SAMPLE_BUILDER
{
    MMP_USHORT initialized; //number of packets sent for this sample
    MMP_ULONG nFrame;       //UVC frame counter. Start with 0 from preview starting
    MMP_ULONG main_size;    //size of the main frame in bytes. (e.g. H264 size in FRAMEBASE_H264_MJPEG)
    MMP_ULONG stream_addr; //starting address of the stream. It would be one of the dual streams.
} UVC_SAMPLE_BUILDER;

static UVC_SAMPLE_BUILDER UvcSampleBuilder;

volatile MMP_ULONG PTS;
//volatile MMP_ULONG PTS_UVC;
//volatile MMP_ULONG Skype_PTS = 0;
#if (SECS_VER > 0)
volatile MMP_ULONG Skype_PTS_H = 0, Skype_PTS_L = 0;
#endif

//MMP_ULONG h264offset;
//MMP_ULONG h264index;

//MMP_USHORT total_packet_count, last_packet_size;

volatile MMP_UBYTE usb_close_Tx_flag;
MMP_UBYTE usb_preclose_Tx_flag;
MMP_UBYTE gbVideoEncDoneFlag;

//extern volatile MMP_ULONG usb_h264_fb_addr;
//MMP_ULONG usb_local_address;
//extern volatile MMP_UBYTE usb_check_reframe;
extern MMPS_3GPRECD_VIDEO_FORMAT m_VideoFmt; 
//MMP_ULONG mjpegoffset, yuv422offset, h264offset;

extern MMP_ULONG    glPCCamCnt;
extern MMP_ULONG    glPCCamJpegSize;
extern MMP_ULONG    glPCCamCompressBufAddr;
extern MMP_ULONG    glPCCamCompressBufSize;
//extern MMP_ULONG   glPCCamLineBufAddr;
extern MMP_ULONG    glPCcamCaptureEnable;
extern MMP_UBYTE    gbStopPreviewEvent;
extern MMP_UBYTE    gbStopMJPEGEvent, gbStopYUV422Event;
extern MMP_ULONG    glPccamResolution;
//extern volatile MMP_UBYTE usb_fb_toggle;
extern void MMPF_USB_ReleaseDm(MMP_UBYTE pipe);
extern volatile MMP_UBYTE gbdrawflag;
extern MMP_BOOL     m_bVidRecdPreviewStatus;

//#ifdef UVC_MJPEG
//extern MMP_UBYTE mjpeg1dat[];
//extern MMP_UBYTE mjpeg2dat[];
//#endif

//#endif

extern MMP_UBYTE  gbUsbHighSpeed;

extern MMP_UBYTE UsbRequestPayload_bmRequestType;
extern MMP_UBYTE UsbRequestPayload_bRequest;
extern MMP_USHORT UsbRequestPayload_wValue;
extern MMP_USHORT UsbRequestPayload_wIndex;
extern MMP_USHORT UsbRequestPayload_wLength;

// ===== for H264 WebCam setting =====
//extern MMP_USHORT m_usResolType;
//extern MMP_USHORT m_usVideoQuality;
//extern MMP_USHORT m_usVideoFlickerMode;
extern MMP_ULONG glCustomTargetSizePerFrame;
// ===================================
//extern MMP_UBYTE  gbVideoCurOutputFrame;
//extern MMP_ULONG   glVideoValidFrameCount;
MMP_ULONG glPCCAM_VIDEO_BUF_ADDR = 0;
MMP_ULONG glPCCAM_VIDEO_BUF_MAX_SIZE = 0;
MMP_ULONG glUSB_UVC_DMA_BUF_ADDR1 = 0;
MMP_ULONG glUSB_UVC_DMA_BUF_ADDR2 = 0;

//extern MMP_ULONG   m_LowerQP;
//extern MMP_ULONG   m_UpperQP;
extern MMP_USHORT      gsVideoEncodeFPS;
extern PCAM_USB_VIDEO_RES gsVidRes ;

MMPF_FCTL_LINK  gUvcPreviewFctlCfg[3] = {
{MMPF_SCALER_PATH_0, MMPF_ICO_PIPE_0, MMPF_IBC_PIPE_0},
{MMPF_SCALER_PATH_1, MMPF_ICO_PIPE_1, MMPF_IBC_PIPE_1},
{MMPF_SCALER_PATH_2, MMPF_ICO_PIPE_2, MMPF_IBC_PIPE_2}
};

MMP_UBYTE gbSkypeEncRes = 0x00;
MMP_UBYTE gbSkypeMode = 0x01; // default is ModeB
MMP_ULONG yuv_preview_size;

MMP_UBYTE gbSnapKeyFlag = 0;

MMP_UBYTE gbLenShadingStatus = 0;
MMP_UBYTE gbDeNoiseStatus = 0;
MMP_UBYTE gbGammaStatus = 0;
MMP_UBYTE gbColorMatrixStatus = 0;
MMP_UBYTE gbEdgeEnhancementStatus = 0;
MMP_UBYTE gbAEStatus = 0;
MMP_UBYTE gbAWBStatus = 0;
MMP_UBYTE gbAudioMode = 0;

MMP_UBYTE gbGraphicLoopBackSource = 0xFF;
MMP_ULONG glGraphicLoopBackCnt = 0;
MMP_UBYTE gbGraLBEvent = 0;

//still image test
MMP_UBYTE gbStillCaptureEvent = STILL_IMAGE_WAITING;
MMP_UBYTE gbCaptureBayerRawFlag = 0;
////////////////
MMP_UBYTE gbStartPreviewEvent = 0;
MMP_UBYTE gbStopPreviewEvent = 0;

extern MMP_USHORT USB_ForceH264IDRFrame(void);


#if USB_UVC_BULK_EP
MMP_UBYTE gbProbeSetCur;
int LinuxProbeCheck = 0;
MMP_UBYTE gbCheckSystemInitFlag = 0;
#endif

MMP_UBYTE gbUVCStartPreviewFlagSet = FALSE;
MMP_UBYTE gbUVCStopPreviewFlagSet = FALSE;

RES_TYPE_CFG gsCurResList[] = 
{
{  PCCAM_640_480  , 640,  480  },
{  PCCAM_160_120  , 160,  120  },
{  PCCAM_176_144  , 176,  144  },
{  PCCAM_320_240  , 320,  240  },
{  PCCAM_352_288  , 352,  288  },
{  PCCAM_640_360  , 640,  360  },
{  PCCAM_800_448  , 800,  448  },
{  PCCAM_800_600  , 800,  600  },
{  PCCAM_960_720  , 960,  720  },
{  PCCAM_1280_720 , 1280, 720  },
{  PCCAM_1920_1080, 1920, 1080 },
{  PCCAM_272_144  , 272,  144  },
{  PCCAM_368_208  , 368,  208  },
{  PCCAM_384_216  , 384,  216  },
{  PCCAM_480_272  , 480,  272  },
{  PCCAM_624_352  , 624,  352  },
{  PCCAM_912_512  , 912,  512  },
{  PCCAM_960_544  , 960,  544  },
{  PCCAM_160_90   , 160,  90   },
{  PCCAM_320_180  , 320,  180  },
{  PCCAM_720_480  , 720,  480  },
{  PCCAM_1024_576 , 1024, 576  },
{  PCCAM_1024_768 , 1024, 768  },
{  PCCAM_1600_1200, 1600, 1200  },
{  PCCAM_1280_800  ,1280, 800  },
{  PCCAM_1280_960  ,1280, 960  },
{  PCCAM_2592_1944 ,2592, 1944  },
{  PCCAM_2048_1536 ,2048, 1536  },
{  PCCAM_480_270  , 480,  270  },
{  PCCAM_800_450  , 800,  450  },
{  PCCAM_2304_1296, 2304, 1296 },
{  PCCAM_128_128  , 128,  128  },
{  PCCAM_64_64    ,  64,   64  },
{  PCCAM_480_320  , 480,  320  },
{  PCCAM_RES_NUM  , 0  ,  0    }
};

SKYPE_RES_TYPE_CFG gsSkypeResList[] = 
{
{  SKYPE_RESOL_160x90   , 160,  90  },
{  SKYPE_RESOL_160x120  , 160,  120  },
{  SKYPE_RESOL_320x180  , 320,  180  },
{  SKYPE_RESOL_320x240  , 320,  240  },
{  SKYPE_RESOL_640x360  , 640,  360  },
{  SKYPE_RESOL_640x480  , 640,  480  },
{  SKYPE_RESOL_1280x720 , 1280, 720  },
#if SKYPE_H264_1080P
{  SKYPE_RESOL_1920x1080, 1920,1080  },
#endif
{  SKYPE_RESOL_RES_NUM  , 0  ,  0    }
};

#if EN_TIME_LOG
TIME_LOG tlH264/*h264 done*/, tlRd0/*read for pipe0*/, tlWr0/*Write start of pipe0*/, tlPkt0/*packet 0*/, tlWr0S,
         tlRd0E;
#endif

H264_FORMAT_TYPE gbCurH264Type = INVALID_H264; // SKYPE_H264 ; // UVC_H264;//SKYPE_H264;//UVC_H264 ;

// Stream CFG : YUY2
const STREAM_CFG gsYUY2Stream_Cfg =
{
#if (SWAP_YUY2_PIPE == 1)
PIPE1_EN,
PIPE_CFG(1, PIPE_CFG_YUY2),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
#elif (SWAP_YUY2_PIPE == 2)
PIPE2_EN,
PIPE_CFG(2, PIPE_CFG_YUY2),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
#else
PIPE0_EN,
PIPE_CFG(0, PIPE_CFG_YUY2),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
#endif
};

#if DRAM_SIZE <= 2
const STREAM_CFG gsYUY2RingStream_Cfg =
{
PIPE0_EN,
PIPE_CFG(0, PIPE_CFG_YUY2 | PIPE_CFG_RING),
PIPE_PH_TYPE_1,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
} ;
#endif

#if CAPTURE_BAYER_RAW_ENABLE
const STREAM_CFG gsRawStream_Cfg =
{
PIPE0_EN,//no pipe
PIPE_CFG(0, PIPE_CFG_YUY2),
PIPE_PH_TYPE_1,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
};
#endif

// Steam CFG : MJPEG
const STREAM_CFG gsMJPEGStream_Cfg =
{
#if (SWAP_MJPG_PIPE == 1)
PIPE1_EN,
PIPE_CFG(1, PIPE_CFG_MJPEG),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
#elif (SWAP_MJPG_PIPE == 2)
PIPE2_EN,
PIPE_CFG(2, PIPE_CFG_MJPEG),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
#else
PIPE0_EN,
PIPE_CFG(0, PIPE_CFG_MJPEG),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
#endif
};

const STREAM_CFG gsNV12Stream_Cfg =
{
PIPE0_EN,
PIPE_CFG(0, PIPE_CFG_NV12),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
} ;

#if SKYPE_MODE_B // not maintained anymore
// Skype Mode B
const STREAM_CFG gsSkyModeBStream_Cfg =
{
PIPE0_EN | PIPE1_EN | PIPE_EN_SYNC,
PIPE_CFG(0, PIPE_CFG_YUY2) | PIPE_CFG(1, PIPE_CFG_H264) ,
PIPE_PH_TYPE_1,PIPE_PH_TYPE_2,PIPE_PH_TYPE_NA,
} ;
#endif

#if USB_FRAMEBASE_H264_MJPEG_STREAM
// H264 + MJPEG dual stream with realtime H.264 encode mode
const STREAM_CFG gsH264RTMJPEGStream_Cfg =
{
PIPE0_EN | PIPE1_EN | PIPE_ASYNC,
PIPE_CFG(0, PIPE_CFG_MJPEG) | PIPE_CFG(1, PIPE_CFG_H264) ,
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,
} ;

// Frame Base H264 + MJPG dual stream with H.264 encode frame mode(for AIT8451)
STREAM_CFG gsH264FrameMJPGStream_Cfg =
{
PIPE0_EN | PIPE1_EN | PIPE2_EN | PIPE_ASYNC,
PIPE_CFG(0, PIPE_CFG_H264) | PIPE_CFG(1, PIPE_CFG_H264) | PIPE_CFG(2, PIPE_CFG_MJPEG),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
} ;
#endif

#if USB_MJPEGH264_STREAM
// H264 + MJPEG dual stream
const STREAM_CFG gsH264MJPEGStream_Cfg =
{
PIPE0_EN | PIPE1_EN ,
PIPE_CFG(0, PIPE_CFG_MJPEG) | PIPE_CFG(1, PIPE_CFG_H264) ,
PIPE_PH_TYPE_1,PIPE_PH_TYPE_1,PIPE_PH_TYPE_NA,
} ;
#endif

#if USB_FRAMEBASE_H264_YUY2_STREAM
// Frame Base H264 + YUY2 dual stream
const STREAM_CFG gsH264FrameYUY2Stream_Cfg =
{
PIPE0_EN | PIPE1_EN ,
PIPE_CFG(0, PIPE_CFG_YUY2) | PIPE_CFG(1, PIPE_CFG_H264) ,
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,
} ;
#endif

#if USB_FRAMEBASE_DUAL_H264_STREAM
// Frame Base H264 + H264 dual stream
const STREAM_CFG gsH264FrameDualStream_Cfg =
{
PIPE0_EN | PIPE1_EN | PIPE_ASYNC,
PIPE_CFG(0, PIPE_CFG_H264) | PIPE_CFG(1, PIPE_CFG_H264),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,
} ;

// Frame Base H264 + H264 + MJPG dual stream
const STREAM_CFG gsH264FrameDual_MJPGStream_Cfg =
{
PIPE0_EN | PIPE1_EN | PIPE2_EN | PIPE_ASYNC,
PIPE_CFG(0, PIPE_CFG_H264) | PIPE_CFG(1, PIPE_CFG_H264) | PIPE_CFG(2, PIPE_CFG_MJPEG),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,PIPE_PH_TYPE_3,
} ;
#endif

#if USB_FRAMEBASE_H264_ONLY
// H264 pure stream (Frame Base H264)
const STREAM_CFG gsH264PureStream_Cfg =
{
#if 1
PIPE1_EN ,
PIPE_CFG(1, PIPE_CFG_H264) ,
PIPE_PH_TYPE_NA,PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,
#else // For test only , output H264, but also encoding MJPEG
PIPE0_EN,
PIPE_CFG(0, PIPE_CFG_H264),
PIPE_PH_TYPE_3,PIPE_PH_TYPE_NA,PIPE_PH_TYPE_NA,
#endif    
} ;
#endif

#if SKYPE_UVC_H264
// Skype UVC H.264 Stream
const STREAM_CFG gsSkypeUVCH264Stream_Cfg =
{
PIPE0_EN | PIPE1_EN,
#if DRAM_SIZE <= 2
PIPE_CFG(0, PIPE_CFG_YUY2 | PIPE_CFG_RING) | PIPE_CFG(1, PIPE_CFG_H264) ,
#else
PIPE_CFG(0, PIPE_CFG_YUY2) | PIPE_CFG(1, PIPE_CFG_H264) ,
#endif
PIPE_PH_TYPE_4,PIPE_PH_TYPE_4,PIPE_PH_TYPE_NA,
} ;
#endif

#if (SECS_VER > 0)
// Skype Transport Stream
const STREAM_CFG gsSkyTransportStream_Cfg =
{
PIPE0_EN | PIPE1_EN,
#if DRAM_SIZE <= 2
PIPE_CFG(0, PIPE_CFG_YUY2 | PIPE_CFG_RING) | PIPE_CFG(1, PIPE_CFG_H264) ,
#else
PIPE_CFG(0, PIPE_CFG_YUY2) | PIPE_CFG(1, PIPE_CFG_H264) ,
#endif
PIPE_PH_TYPE_1,PIPE_PH_TYPE_1,PIPE_PH_TYPE_NA,
} ;
#endif  

//  H264 XU structure.
#if SKYPE_UVC_H264


#if BLOCK_2_UVC_INTERFACE
#define BLOCK_2_UVC_INTERFACE_PROC_VER  (2)//2:@ VS_COMMIT SET_CUR/GET_CUR; 1:@ VS_PROBE SET_CUR/VS_COMMIT GET_CUR;
#endif
MMP_UBYTE gbProbeCommitCamera;//0:MAIN_SENSOR, 1:SUB_SENSOR

extern MMP_UBYTE gbSwitchSensor;

#if SUPPORT_METHOD_1_MJPEG_CAPTURE_EXIF && (CUSTOMER == ASU)
__align(4) MMP_UBYTE ExifEncodeData[] = {
//ExifHeaderEncode
//0xFF, 0xD8, //EXIF_SOI
0xFF, 0xE1, //EXIF_APP1_MARKER,
0x00, 0xB7, //APP1 data size
0x45, 0x78, 0x69, 0x66, //EXIF_ID,
0x00, 0x00, 
//TifHeaderEncode
0x49, 0x49, //TIF_II_FORMAT,
0x2A, 0x00, 
0x08, 0x00, 0x00, 0x00,
//0th IFD
0x03, 0x00, //Interoperability Number
0x0F, 0x01, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, //Make
0x10, 0x01, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, //Model
0x69, 0x87, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, //Sub Exif point
//Next IFD offset
0x00, 0x00, 0x00, 0x00,
//Value longer than 4byte of 0th IFD
'A', 'S', 'U', 'S', ' ', 'V', 'i', 'v', 'o', '.', //Make Value
'T', 'X', '-', '3', '0', //Model Value
//Sub IFD
0x06, 0x00,
0x9A, 0x82, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, 0x00, //ExposureTime
0x9D, 0x82, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, //FNumber
0x27, 0x88, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, //ISOSpeedRatings
0x04, 0x92, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x00, //ExposureBiasValue
0x09, 0x92, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, //Flash
0x0A, 0x92, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0xA7, 0x00, 0x00, 0x00, //FocalLength
0x00, 0x00, 0x00, 0x00, //Next IFD Offset
//Value longer than 4byte of 0th IFD
0x0A, 0x00, 0x00, 0x00, 0xC4, 0x09, 0x00, 0x00, //ExposureTime Value
0x22, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, //FNumber Value
0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, //ExposureBias Value
0x55, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00 //FocalLength Value
} ;
#endif

// Sean@2011_01_22 for UVC yuy2 + h264 dual stream and wrapped by JPEG header
// The header for H264+YUY2 payload format
__align(4) static char gbJpegHeader[] =
{
0xFF,0xD8,0xFF,0xDD,0x00,0x04,0x00,0x00,
// mark for JPEG snooper tool warning
/*
0xFF,0xDA,0x00,0x0C,
0x03,0x01,0x00,0x02,0x11,
0x03,0x11,0x00,0x3F,0x00,
*/
0xFF,0xD9
};

H264_ENCODER_VFC_CFG gsH264EncoderVFC_Cfg_Cur =
{
1280, // Width
720, // Height
0, // FramePeriod
UT_DEFAULT, // UsageTarget
DUAL_STREAM_EN | DUAL_MJPEG_H264,
} ;
#endif

//#if USB_UVC_H264==1
#if SKYPE_MODE_B || USB_MJPEGH264_STREAM

H264_ENCODER_VFC_CFG gsH264EncoderVFC_Cfg_Def =
{
1280, // Width
720, // Height
0, // FramePeriod
UT_DEFAULT, // UsageTarget
DUAL_STREAM_EN | DUAL_MJPEG_H264,
} ;




/*
H264_ENCODER_CC_CFG gsH264EncoderCC_Cfg_Def = 
{
    (1 * 1024 * 1024 ), // BitRate
    (2 * 1024 * 1024 ), // BitRate Max
    1000,               // RateControlDelay
    0,                  // IDR frame frequency
    0,                  // AirRate
    0,                  // SliceSize
    0,                  // SliceMode
    SF_NAL,             // SliceFormat
    PROFILE_BASELINE,   // profile
    RCM_CBR,            // RateControlMode
    QM_USER_DEF,        // QuantizerMax
    QM_USER_DEF,         // QuantizerMin
} ;

H264_ENCODER_CC_CFG gsH264EncoderCC_Cfg_Cur = 
{
    (1 * 1024 * 1024 ), // BitRate
    (2 * 1024 * 1024 ), // BitRate Max
    1000,               // RateControlDelay
    0,                  // IDR frame frequency
    0,                  // AirRate
    0,                  // SliceSize
    0,                  // SliceMode
    SF_NAL,             // SliceFormat
    PROFILE_BASELINE,   // profile
    RCM_CBR,            // RateControlMode
    QM_USER_DEF,        // QuantizerMax
    QM_USER_DEF,         // QuantizerMin
} ;


H264_ENCODER_RC_CFG gsH264EncoderRC_Cfg_Def =
{
    0,              // FramePeriod ;
    ( 1 * 1024 * 1024 ), // BitRate
} ;

H264_ENCODER_RC_CFG gsH264EncoderRC_Cfg_Min =
{
    0,              // FramePeriod ;
    ( 256 * 1024  ), // BitRate
} ;

H264_ENCODER_RC_CFG gsH264EncoderRC_Cfg_Max =
{
    0,              // FramePeriod ;
    ( 2 * 1024 * 1024 ), // BitRate
} ;

H264_ENCODER_RC_CFG gsH264EncoderRC_Cfg_Cur =
{
    0,              // FramePeriod ;
    ( 1 * 1024 * 1024 ), // BitRate
} ;


MMP_UBYTE   gbH264EncoderFTC_Cfg = FT_IVIDEO_IDR_FRAME ; // IDR frame only

MMP_USHORT  gsH264EncoderCDC_Cfg = 0 ; // Camera Delay Control

H264_ENCODER_FILTER_CFG gsH264EncoderFilter_Cfg =
{
0,      // TemporalFilterStrength.
0       // SpatialFilterStrength 
} ;
*/
#endif


//
// VCI control unit
//
VC_CMD_CFG VCI_ERROR_CFG = {
(CAP_GET_INFO_CMD | CAP_GET_CUR_CMD) ,
(INFO_GET_SUPPORT),
1,
0,0,0,0,0    
} ;

//
// SU input control unit
//
#if SUPPORT_SU
VC_CMD_CFG  SU_INPUT_SELECT_CFG =
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
1,
(CMD_VALUE) 0x01,(CMD_VALUE) 0x01,(CMD_VALUE) 0x01,(CMD_VALUE) 0x01,(CMD_VALUE) 0x01
} ;
#endif

//
// PU control unit 
//
VC_CMD_CFG  PU_BACKLIGHT_CFG = // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) BLC_DEF,(CMD_VALUE) BLC_MIN,(CMD_VALUE) BLC_MAX,(CMD_VALUE) BLC_DEF
} ;

VC_CMD_CFG PU_BRIGHTNESS_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) BRI_DEF,(CMD_VALUE) BRI_MIN,(CMD_VALUE) BRI_MAX,(CMD_VALUE) BRI_DEF
} ;


VC_CMD_CFG PU_CONTRAST_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) CON_DEF,(CMD_VALUE) CON_MIN,(CMD_VALUE) CON_MAX,(CMD_VALUE) CON_DEF
};

VC_CMD_CFG PU_POWERLINEREQ_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
1,
(CMD_VALUE) 0x01,(CMD_VALUE) BAND_DEF,(CMD_VALUE) BAND_DISABLE,(CMD_VALUE) BAND_MAX,(CMD_VALUE) BAND_DEF
};

VC_CMD_CFG PU_HUE_CFG =  // (Disabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) HUE_DEF,(CMD_VALUE) HUE_MIN,(CMD_VALUE) HUE_MAX,(CMD_VALUE) HUE_DEF
};

VC_CMD_CFG PU_SATURATION_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) SAT_DEF,(CMD_VALUE) SAT_MIN,(CMD_VALUE) SAT_MAX,(CMD_VALUE) SAT_DEF
};

VC_CMD_CFG PU_SHARPNESS_CFG =   // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) SHA_DEF,(CMD_VALUE) SHA_MIN,(CMD_VALUE) SHA_MAX,(CMD_VALUE) SHA_DEF
};

VC_CMD_CFG PU_GAMMA_CFG =  // (Disabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) GAM_DEF,(CMD_VALUE) GAM_MIN,(CMD_VALUE) GAM_MAX,(CMD_VALUE) GAM_DEF
};

VC_CMD_CFG PU_WB_TEMP_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x000A,(CMD_VALUE) WBT_DEF,(CMD_VALUE) WBT_MIN,(CMD_VALUE) WBT_MAX,(CMD_VALUE) WBT_DEF
};

VC_CMD_CFG PU_WB_TEMP_AUTO_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
1,
(CMD_VALUE) 0x01,(CMD_VALUE) AWB_DEF,(CMD_VALUE) AWB_MIN,(CMD_VALUE) AWB_MAX,(CMD_VALUE) AWB_DEF
};

VC_CMD_CFG PU_GAIN_CFG =  // (Enabled) 
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_GET_SUPPORT | INFO_SET_SUPPORT),
2,
(CMD_VALUE) 0x01,(CMD_VALUE) GAIN_DEF,(CMD_VALUE) GAIN_MIN,(CMD_VALUE) GAIN_MAX,(CMD_VALUE) GAIN_DEF
};
// Still need to add the following
// 1. Gain



//
// CT control unit 
//
VC_CMD_CFG CT_FOCUS_ABS_CFG =  // (Disabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT | INFO_AUTO_MODE_SUPPORT | INFO_AUTOUPDATE_CONTROL_SUPPORT),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) AAF_DEF,(CMD_VALUE) AAF_MIN,(CMD_VALUE) AAF_MAX,(CMD_VALUE) AAF_DEF
};

VC_CMD_CFG CT_FOCUS_AUTO_CFG = // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
1,
(CMD_VALUE) 0x01,(CMD_VALUE) AUTOAF_DEF,(CMD_VALUE) AUTOAF_MIN,(CMD_VALUE) AUTOAF_MAX,(CMD_VALUE) AUTOAF_DEF
};

VC_CMD_CFG CT_ZOOM_ABS_CFG =  // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT /*| INFO_ASYNC_CONTROL_SUPPORT*/),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) ZOM_DEF,(CMD_VALUE) ZOM_MIN,(CMD_VALUE) ZOM_MAX,(CMD_VALUE) ZOM_DEF
};

VC_CMD_CFG CT_EXPOSURE_TIME_ABS_CFG =  // (Disabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT | INFO_AUTO_MODE_SUPPORT | INFO_AUTOUPDATE_CONTROL_SUPPORT),
4,
(CMD_VALUE) 0x0001,(CMD_VALUE) EPV_DEF,(CMD_VALUE) EPV_MIN,(CMD_VALUE) EPV_MAX,(CMD_VALUE) EPV_DEF
};

VC_CMD_CFG CT_AE_MODE_CFG = // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD |  /*CAP_GET_MIN_CMD | CAP_GET_MAX_CMD |*/ CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
1,
(CMD_VALUE) 0x07,(CMD_VALUE) AEC_DEF,(CMD_VALUE) AEC_MIN,(CMD_VALUE) AEC_MAX,(CMD_VALUE) AEC_DEF
};

MMP_ULONG glPanTiltCur[2];
#if CUSTOMER == ASU
/*
typedef struct _ASU_CT_CUS_2 {
    MMP_UBYTE bVer;
    MMP_UBYTE bAfLock;
    MMP_UBYTE bLastError;
    MMP_UBYTE bAeLock;
} ASU_CT_CUS_2;
*/

VC_CMD_CFG CT_PANTILT_RELATIVE_CFG =   // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT /*| INFO_ASYNC_CONTROL_SUPPORT*/),
4,
(CMD_VALUE) 0x01010101, (CMD_VALUE) 0x21000000, (CMD_VALUE) 0x21000000, (CMD_VALUE) 0x21FFFFFF, (CMD_VALUE) 0x21000000
};

const MMP_ULONG glPanTiltDef[2] = {0,0};
const MMP_ULONG glPanTiltMax[2] = {(1944 << 16) | 2592, (1944 << 16) | 2592};//(top << 16) | left, (bottom << 16) | right
const MMP_ULONG glPanTiltMin[2] = {(0 << 16) | 0, (1 << 16) | 1};//(top << 16) | left, (bottom << 16) | right
const MMP_ULONG glPanTiltRes[2] = {1, 1};
#else
MMP_ULONG glPanTiltCur[2];
const MMP_ULONG glPanTiltDef[2] = {PAN_DEF,TILT_DEF } ;
const MMP_ULONG glPanTiltMax[2] = {PAN_MAX,TILT_MAX } ;
const MMP_ULONG glPanTiltMin[2] = {PAN_MIN,TILT_MIN } ;
const MMP_ULONG glPanTiltRes[2] = {PANTILT_RES,PANTILT_RES } ;
#endif

#if UVC_IT_BITMAP & (1 << 11) && (SUPPORT_DIGITAL_PAN)//ROLL(ABS)
VC_CMD_CFG CT_PANTILT_ABS_CFG =   // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT /*| INFO_ASYNC_CONTROL_SUPPORT*/),
8,
(CMD_VALUE) glPanTiltRes,(CMD_VALUE) glPanTiltDef,(CMD_VALUE) glPanTiltMin,(CMD_VALUE) glPanTiltMax,
(CMD_VALUE) glPanTiltCur
};
#endif

#if UVC_IT_BITMAP & (1 << 13) && (CUSTOMER == ASU)//ROLL(ABS)
VC_CMD_CFG CT_ROLL_ABS_CFG =   // (Enabled)
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT /*| INFO_ASYNC_CONTROL_SUPPORT*/),
2,
(CMD_VALUE) 0x0001,(CMD_VALUE) 0x0001,(CMD_VALUE) 0x0000,(CMD_VALUE) 0x0007,(CMD_VALUE) 0x0000
};
#endif

#if UVC_IT_BITMAP & (1<<21)//CT_REGION_OF_INTEREST
typedef struct _CT_ROI
{
    MMP_USHORT wROI_Top;
    MMP_USHORT wROI_Left;
    MMP_USHORT wROI_Bottom;
    MMP_USHORT wROI_Right;
    MMP_USHORT bmAutoControls;
} CT_ROI;

#define CT_ROI_AE  0x0001
#define CT_ROI_AI  0x0002
#define CT_ROI_AWB 0x0004
#define CT_ROI_AF  0x0008
#define CT_ROI_AFD 0x0010 //auto face detect
#define CT_ROI_ADT 0x0020 //auto detect & track
#define CT_ROI_IS  0x0040 //image stabilization
#define CT_ROI_HQ  0x0080 //high quality

const CT_ROI CtRoiRes = {1, 1, 1, 1, 1};
const CT_ROI CtRoiMax = {2592 - 1, 1944 - 1, 2592 - 1, 1944 - 1, 0x00FF};
CT_ROI CtRoiCur;

VC_CMD_CFG CT_ROI_CFG =
{
(CAP_SET_CUR_CMD | CAP_GET_INFO_CMD | CAP_GET_CUR_CMD | CAP_GET_DEF_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | CAP_GET_RES_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT /*| INFO_ASYNC_CONTROL_SUPPORT*/),
sizeof(CT_ROI),
(CMD_VALUE) & CtRoiRes,(CMD_VALUE) 0,(CMD_VALUE) 0,(CMD_VALUE) & CtRoiMax,(CMD_VALUE) & CtRoiCur
};
#endif

#if USE_COMMON_STALL
/**
 *  Stall and assign error code
 * @param[in] uvc_error The UVC error code
 */
void usb_vc_stall(const u_char uvc_error)
{
    gbVCERRCode = uvc_error;
    UsbWriteEp0CSR(SET_EP0_SENDSTALL);
}

/**
 *  Stall and return RX served and assign error code
 * @param[in] uvc_error The UVC error code
 */
void usb_vc_stall_rx(const u_char uvc_error)
{
    gbVCERRCode = uvc_error;
    UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
}
#endif

// Still need to add the following
// 1. Auto Exposure mode
// 2. Auto Exposure priority
// 3. Exposure time (absolute)


void USB_PUT_FIFO(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit, MMP_ULONG data, MMP_ULONG data1)
{
    MMP_ULONG val[2] ;
    val[0] = data;
    val[1] = data1;
    USB_PUT_FIFO_DATA(req, ubEpNum, unit, (MMP_UBYTE *) val);
}

void USB_PUT_FIFO_DATA(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit, MMP_UBYTE *data)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    MMP_USHORT i;
    if(ubEpNum == MMPF_USB_EP0){
        USBInPhase = req;           
        USBEP0TxCnt = unit;
    }
    // RTNA_DBG_Str3("++DATA.S\r\n");
    if(data){
        for(i = 0;i < unit;i++){
            //RTNA_DBG_Byte3(data[i]);
            pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B = data[i];
        }
    }
    else{
        for(i = 0;i < unit;i++){
            //RTNA_DBG_Byte3(0);
            pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B = 0 ;
        }
    }
    //RTNA_DBG_Str3("\r\n--DATA.E\r\n");

    if(ubEpNum == MMPF_USB_EP0){
        usb_ep0_in();
    }
}

void USB_GET_FIFO_DATA(MMP_UBYTE ubEpNum, MMP_USHORT fifo_len, MMP_UBYTE *buf, MMP_USHORT buf_len)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    MMP_USHORT i , rd_len = 0,skip_len = 0 ;

    MMP_UBYTE skip ;

    if(fifo_len > buf_len){
        rd_len = buf_len ;
        skip_len = fifo_len - rd_len ;
    }
    else{
        rd_len = fifo_len ;
    }


    // Clean buf
    for(i = 0;i < buf_len;i++){
        buf[i] = 0 ;
    }

    // Read valid data into buf
    for(i = 0;i < rd_len ;i++){
        buf[i] = pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B;
    }

    // Skip 
    for(i = 0;i < skip_len ;i++){
        skip = pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B;
    }
}

void USB_SET_FIFO_DATA(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit, MMP_UBYTE val)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    MMP_USHORT i;
    if(ubEpNum == MMPF_USB_EP0){
        USBInPhase = req;           
        USBEP0TxCnt = unit;
    }

    for(i = 0;i < unit;i++){
        //RTNA_DBG_Byte3(data[i]);
        pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B = val;
    }

    if(ubEpNum == MMPF_USB_EP0){
        usb_ep0_in();
    }
}

__inline void USB_SET_FIFO_DATA_ONE(MMP_UBYTE req, MMP_UBYTE ubEpNum, MMP_UBYTE unit)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    pUSB_CTL->USB_FIFO_EP[ubEpNum].FIFO_B = 0x01;
    USB_PUT_FIFO_DATA(req, ubEpNum, unit - 1, 0);
}

#if USE_COMMON_EP0_IN
void usb_vc_put_ep0_data(MMP_UBYTE in_phase, MMP_UBYTE size, MMP_UBYTE *const data)
{
    USB_PUT_FIFO_DATA(in_phase, MMPF_USB_EP0, size, data);
}

/** @brief Put ep0 data with a max length and set the in phase state.

The default will put the data based on current USBEP0TxCnt value.
@remark Because it based on current USBEP0TxCnt, the caller might need to update this value before using this function.

@param[in] in_phase The in phase state.
@param[in] max_len The minimal size to be put in bytes.
@param[in] data The pointer to the minimal size data
*/
void usb_vc_put_ep0_at_most(MMP_UBYTE in_phase, MMP_USHORT max_len, MMP_UBYTE *data)
{
    if(USBEP0TxCnt > max_len){
        USBEP0TxCnt = max_len;
    }
    usb_vc_put_ep0_data(in_phase, USBEP0TxCnt, data);
}
#endif

#if USE_COMMON_EP0_OUT
// get the data based on current USB command UsbRequestPayload_wLength
void usb_vc_get_ep0_data(MMP_UBYTE *const data)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
    u_short i;
    u_char tempb;

    USBOutData = 0;
    if(data == NULL_GET){
        for(i = 0;i < UsbRequestPayload_wLength;i++){
            tempb = pUSB_CTL->USB_FIFO_EP[MMPF_USB_EP0].FIFO_B;
        }
    }
    else{
        USB_GET_FIFO_DATA(MMPF_USB_EP0, UsbRequestPayload_wLength, data, UsbRequestPayload_wLength);
        //for(i=0;i<UsbRequestPayload_wLength;i++) {
        //   *(data+i) = pUSB_CTL->USB_FIFO_EP[MMPF_USB_EP0].FIFO_B;
        //}
    }
}
#endif

#if USE_CS_OUT_RANGE_CHK
#define CS_OUT_RANGE_DBG_LEVEL 1
#define RETURN_IF_USE_RANGE_CHK return
/** @brief Check if the value is out of range and config the UVC error.

@param[in] cfg The cfg value.
@param[in] value The value to be checked.
@param[in] str The debug message to be printed out. If the DBG_LEVEL is smaller than CS_OUT_RANGE_DBG_LEVEL,
               it would not be compiled to save the code size.
@retval 1: out of range. 0:in range. 2: Not applicable, the command length is too big.
@pre This function is used in cs_out functions only because it would change UVC & USB FW state.
@remark Please always usb_vc_cmd_check_range instead of _usb_vc_cmd_check_range
*/
#if DBG_LEVEL >= CS_OUT_RANGE_DBG_LEVEL
#define usb_vc_cmd_check_default_range(cfg,value,str) _usb_vc_cmd_check_default_range(cfg, (int)value, str)
MMP_USHORT _usb_vc_cmd_check_default_range(VC_CMD_CFG const * const cfg, MMP_LONG value, char* const str)
#else
#define usb_vc_cmd_check_default_range(cfg,value,str) _usb_vc_cmd_check_default_range(cfg, (int)value)
MMP_USHORT _usb_vc_cmd_check_default_range(VC_CMD_CFG const * const cfg, MMP_LONG value)
#endif
{
    if(cfg->bCmdLen > 4){
        usb_vc_stall_rx(CONTROL_UNKNOWN);//the caller could not use this function for pure value comparison.
        return 1;
    }

    // The legth check, signed and unsigned check still need revise!! bossino@20121228
    if(cfg->bCmdLen == 2){
        MMP_SHORT usValue, usMinValue, usMaxValue;
        usValue = (MMP_SHORT) value;
        usMinValue = *(MMP_SHORT *) &cfg->dwMinVal;
        usMaxValue = *(MMP_SHORT *) &cfg->dwMaxVal;

        if((usValue > usMaxValue) || (usValue < usMinValue)){
#if DBG_LEVEL >= CS_OUT_RANGE_DBG_LEVEL
            DBG_S(0, str);
            DBG_W(0, value);
            DBG_S(0, " is OOR\r\n");//out of range
#endif
            // unsupported
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            return 1;
        }
    }
    else{
        if((value > (int) cfg->dwMaxVal) || (value < (int) cfg->dwMinVal)){
#if DBG_LEVEL >= CS_OUT_RANGE_DBG_LEVEL
            DBG_S(0, str);
            DBG_W(0, value);
            DBG_S(0, " is OOR\r\n");//out of range
#endif
            // unsupported
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            return 1;
        }
    }
    return 0;
}

/** @brief Get the value from the host and check if the value is out of range and config the UVC error.

@param[in] cfg The cfg value.
@param[out] value The address of the value to be written if the range is correct.
@param[in] str The debug message to be printed out. If the DBG_LEVEL is smaller than CS_OUT_RANGE_DBG_LEVEL,
               it would not be compiled to save the code size.
*/
#if DBG_LEVEL >= CS_OUT_RANGE_DBG_LEVEL
#define usb_vc_cmd_get_simple_value(cfg,pVal,str) _usb_vc_cmd_get_simple_value(cfg, (void*)pVal, str)
MMP_USHORT _usb_vc_cmd_get_simple_value(VC_CMD_CFG const * const cfg, void * const pVal, char* const str)
#else
#define usb_vc_cmd_get_simple_value(cfg,pVal,str) _usb_vc_cmd_get_simple_value(cfg, (void*)pVal)
MMP_USHORT _usb_vc_cmd_get_simple_value(VC_CMD_CFG const * const cfg, void * const pVal)
#endif
{
    MMP_LONG value;
    MMP_USHORT ret;
    MMP_USHORT i;
    MMP_USHORT data_len;

    USBOutData = 0;

    value = 0;

    data_len = cfg->bCmdLen;

    if(UsbRequestPayload_wLength != cfg->bCmdLen)    //for ISB-IF Gain-control
    {
        data_len = UsbRequestPayload_wLength;
        dbg_printf(0, "[Warning] The real data length %x is not as expected %x!!\r\n", UsbRequestPayload_wLength,
                           cfg->bCmdLen);
    }

    USB_GET_FIFO_DATA(MMPF_USB_EP0, data_len, (MMP_UBYTE *) &value, sizeof(value));

    ret = usb_vc_cmd_check_default_range(cfg, value, str);
    if(ret == 0){
        //success
        for(i = 0;i < cfg->bCmdLen;i++){
            ((MMP_UBYTE *) pVal)[i] = ((MMP_UBYTE *) &value)[i];
        }
    }
    return ret;
}
#else
#define RETURN_IF_USE_RANGE_CHK
#endif

void usb_vc_cmd_cfg(MMP_UBYTE req, VC_CMD_CFG *cfg, CMD_VALUE const cur_val)
{
    int print = 0;
    const CMD_VALUE *pVal = 0;
#define isPointer cfg->bCmdLen > 4

    /*if((cfg==&FU_VOL_CFG)) {
        RTNA_DBG_Str3("FU_VOL_CFG\r\n");
        print = 1 ;
    }
    */
    /*
    if((cfg==&CT_FOCUS_ABS_CFG)) {
        RTNA_DBG_Str3("CT_FOCUS_ABS_CFG\r\n");
        print = 1 ;
    }
    */
    //if(cfg->bCmdLen > 4) {
    //    isPointer = 1;
    //}
    if(print){
        dbg_printf(3, "vc.req:%02X\r\n", req);
        if((SET_CUR_CMD == req) || (GET_CUR_CMD == req)){
            dbg_printf(3, "vc.val %X\r\n", (MMP_ULONG) cur_val);
        }
    }

    switch(req){
    case SET_CUR_CMD:
        if(cfg->bCmdCap & CAP_SET_CUR_CMD){
            if(cfg->bInfoCap & INFO_AUTO_MODE_SUPPORT){
                // cfg addr == Focus absolute control
                if(cfg == &CT_FOCUS_ABS_CFG){
                    if(gbAutoFocus){
                        usb_vc_stall(CONTROL_INVALID_CONTROL);
                    }
                    else{
                        USBOutPhase = req;
                        USBOutData = 1 ;
                    }
                }
                else{
                    USBOutPhase = req;
                    USBOutData = 1 ;
                }
            }
            else{
                USBOutPhase = req;
                USBOutData = 1 ;
            }
        }
        else{
            goto invalid_req ;
        }
        break;
    case GET_CUR_CMD:
        if(cfg->bCmdCap & CAP_GET_CUR_CMD){
            pVal = &cur_val;
#if 0
if(cfg->bCmdLen > 4) {
     USB_PUT_FIFO_DATA(req,MMPF_USB_EP0,cfg->bCmdLen,(MMP_UBYTE *)cur_val);   
} else {
    
     USB_PUT_FIFO_DATA(req,MMPF_USB_EP0,cfg->bCmdLen,(MMP_UBYTE *)&cur_val);                
}
#endif
        }
        else{
            goto invalid_req;
        }
        break;    
    case GET_INFO_CMD:
        if(cfg->bCmdCap & CAP_GET_INFO_CMD){
            USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, 1, (MMP_UBYTE *) &cfg->bInfoCap) ;
        }
        else{
            goto invalid_req;
        } 
        break ;

    case GET_DEF_CMD:
        if(cfg->bCmdCap & CAP_GET_DEF_CMD){
            if(print){
                dbg_printf(3, "vc.def: %X\r\n", (MMP_ULONG) cfg->dwDefVal);
            }
            pVal = &cfg->dwDefVal;
#if 1
            if(*pVal == 0 && (isPointer)){
                USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0x00);
                pVal = 0;
            }
#else
            if(cfg->bCmdLen > 4){
                if(cfg->dwDefVal)
                    USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) cfg->dwDefVal);
                else
                    USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0x00);
            }
            else{
                USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) &cfg->dwDefVal);
            }
#endif
        }
        else{
            goto invalid_req;
        }
        break;    
    case GET_MAX_CMD:
        if(cfg->bCmdCap & CAP_GET_MAX_CMD){
            if(print){
                dbg_printf(3, "vc.max: %X\r\n", (MMP_ULONG) cfg->dwMaxVal);
            }
            pVal = &cfg->dwMaxVal;
#if 1
            if(*pVal == 0 && (isPointer)){
                USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0xFF);
                pVal = 0;
            }
#else
            if(cfg->bCmdLen > 4){
                if(cfg->dwMaxVal)
                    USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) cfg->dwMaxVal);
                else
                    USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0xFF);
            }
            else{
                USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) &cfg->dwMaxVal);
            }
#endif
        }
        else{
            goto invalid_req;
        }
        break;    
    case GET_MIN_CMD:
        if(cfg->bCmdCap & CAP_GET_MIN_CMD){
            if(print){
                dbg_printf(3, "vc.min: %X\r\n", (MMP_ULONG) cfg->dwMinVal);
            }
            pVal = &cfg->dwMinVal;
#if 1
            if(*pVal == 0 && (isPointer)){
                pVal = 0;
                USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0);
            }
#else
            if(cfg->bCmdLen > 4){
                if(cfg->dwMinVal)
                    USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) cfg->dwMinVal);
                else
                    USB_SET_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, 0);
            }
            else{
                USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) &cfg->dwMinVal);
            }
#endif
        }
        else{
            goto invalid_req;
        }
        break;    
    case GET_RES_CMD:
        if(cfg->bCmdCap & CAP_GET_RES_CMD){
            if(print){
                dbg_printf(3, "vc.res: %X\r\n", (MMP_ULONG) cfg->dwResVal);
            }
            pVal = &cfg->dwResVal;
#if 1
            if(*pVal == 0 && (isPointer)){
                pVal = 0;
                USB_SET_FIFO_DATA_ONE(req, MMPF_USB_EP0, cfg->bCmdLen);
            }
#else
            if(cfg->bCmdLen > 4){
                if(cfg->dwResVal)
                    USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) cfg->dwResVal);
                else
                    USB_SET_FIFO_DATA_ONE(req, MMPF_USB_EP0, cfg->bCmdLen);
            }
            else{
                USB_PUT_FIFO_DATA(req, MMPF_USB_EP0, cfg->bCmdLen, (MMP_UBYTE *) &cfg->dwResVal);
            }
#endif
        }
        else{
            goto invalid_req;
        }
        break;
    case GET_LEN_CMD:
        if(cfg->bCmdCap & CAP_GET_LEN_CMD){
            usb_vc_put_ep0_data(req, 2, (MMP_UBYTE *) &(cfg->bCmdLen));
        }
        else{
            goto invalid_req;
        }
        break;    
    default:
        invalid_req: 
        if(print){
            RTNA_DBG_Str3("Cfg.Err\r\n");
        }   
        usb_vc_stall(CONTROL_INVALID_REQUEST);
        break ;
    }

    if(0 != pVal){
        if(isPointer){
            usb_vc_put_ep0_data(req, cfg->bCmdLen, (u_char *) *pVal);
        }
        else{
            usb_vc_put_ep0_data(req, cfg->bCmdLen, (u_char *) pVal);
        }
    }

    //if(print) {
    //    RTNA_DBG_Str3("Cfg.End\r\n");
    //}   
}

void usb_vc_update_automode(void)
{
    if(gbUpdAE){
        gbUpdAE = 0;
        usb_vc_update_async_mode(UVC_IT_ID, CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, 1, &gbEVInfo, 1);
    } 
    if(gbUpdAWB){
        gbUpdAWB = 0;
        usb_vc_update_async_mode(UVC_PU_ID, PU_WHITE_BALANCE_TEMPERATURE_CONTROL, 1, &gbTemperInfo, 1);
    }
    if(gbUpdAG){
        gbUpdAG = 0;
        usb_vc_update_async_mode(UVC_PU_ID, PU_GAIN_CONTROL, 1, &gbGainInfo, 1);
    }
}

// Async. Mode for VC control
void usb_vc_update_async_mode(MMP_UBYTE bOriginator, MMP_UBYTE bSelector, MMP_UBYTE bAttribute, void *bValue,
                              MMP_UBYTE bValUnit)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = 0x01;//VideoControl interface
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = bOriginator;
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = 0x00;//Control Change
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = bSelector;// Control Selector
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = bAttribute;//0:value,1:info,2:failure
    USB_PUT_FIFO_DATA(0, PCCAM_EX_EP_ADDR, bValUnit, (MMP_UBYTE *) bValue) ;
    EnableEx(PCCAM_EX_EP_ADDR);
}


void usb_vc_capture_trigger(MMP_UBYTE pressed)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    //RTNA_DBG_Str(0, "  ** usb_vc_capture_trigger() **\r\n");
    //RTNA_DBG_Short(0, pressed);     
    //RTNA_DBG_Str(0, "-pressed\r\n"); 
    dbg_printf(3, "USB IntEP : %d\r\n", pressed);

    if(gbSnapKeyFlag == pressed)
        return;

    gbSnapKeyFlag = pressed;

    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = 0x02;//VideoStream interface
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = UVC_D1_STREAM_IF1_NO;
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = 0x00;//Button Press
    pUSB_CTL->USB_FIFO_EP[PCCAM_EX_EP_ADDR].FIFO_B = pressed;//0:released,1:pressed

    EnableEx(PCCAM_EX_EP_ADDR);
}

#if SUPPORT_HID_FUNC
void usb_hid_trigger(MMP_UBYTE event, MMP_UBYTE modifier  )
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    RTNA_DBG_Str(3, "  ** usb_hid_trigger() 3**\r\n");
    RTNA_DBG_Short(3, event);     
    RTNA_DBG_Str(3, "-event\r\n"); 
	//KK_Debug4("in");
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = modifier;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;

    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = event;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[HID_EP_ADDR].FIFO_B = 0x00;


    EnableEx(HID_EP_ADDR);
}
/*
void usb_hid_trigger(MMP_UBYTE event)
{
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;

    RTNA_DBG_Str(3, "  ** usb_hid_trigger() 3**\r\n");
    RTNA_DBG_Short(3, event);     
    RTNA_DBG_Str(3, "-event\r\n"); 

    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;

    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x09;//event;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;
    pUSB_CTL->USB_FIFO_EP[0x3].FIFO_B = 0x00;

    EnableEx(PCCAM_EX_EP_ADDR);
}
*/
#endif

/*
void gpio_c_irq_handler()
{
    usb_vc_capture_trigger(0);
}
*/

void uvc_init(MMP_BOOL reset_val)
{
#if UVC_MOVE_DMA_EN
    volatile MMP_UBYTE *pt1 = (volatile MMP_UBYTE *) glUSB_UVC_DMA_BUF_ADDR1;     
    volatile MMP_UBYTE *pt2 = (volatile MMP_UBYTE *) glUSB_UVC_DMA_BUF_ADDR2;  
    MMP_USHORT i;
    MMP_ULONG  n = UVCTxFIFOSize *UVC_DMA_3K_NUM;
#if UVC_DMA_3K_NUM == 0
    n = UVC_DMA_SIZE ;
#endif

    if(glUSB_UVC_DMA_BUF_ADDR1 && glUSB_UVC_DMA_BUF_ADDR2){
        for(i = 0;i < n;i++){
            if(i % 2 == 0){
                pt1[i] = 0x00;
                pt2[i] = 0x00;
            }
            else{
                pt1[i] = 0x80;
                pt2[i] = 0x80;
            }
        }
    }
#endif

    UvcSampleBuilder.initialized = 0;
    UvcSampleBuilder.nFrame = 0;
    usb_close_Tx_flag = 0;
    usb_preclose_Tx_flag = 0;
    gbVideoEncDoneFlag = 0;

    if(reset_val){
        glPan = PAN_DEF;
        glTilt = TILT_DEF ;
        gsZoom = ZOM_DEF;
        gsBacklight = BLC_DEF;
        gsTemper = WBT_DEF;
        gsSaturation = SAT_DEF;
        gsContrast = CON_DEF;
        gsBrightness = BRI_DEF;
        gsHue = HUE_DEF;
        gsGamma = GAM_DEF;
        gsSharpness = SHA_DEF;
        gsGain = GAIN_DEF;
        gsEV = EPV_DEF;
        gbBandFilter = BAND_DEF;

        gsAFocus = AAF_DEF;
        gbAutoFocus = AUTOAF_DEF;

        gbAE = AEC_DEF;
        gblastAE = gbAE;
        gbAWB = AWB_DEF;
        gblastAWB = gbAWB;

        // sean@2011_03_15, reset 3A, reinit again after reset
        MMPF_Sensor_Set3AState(MMPF_SENSOR_3A_RESET);
        MMPF_Sensor_SetBufferSize(0);
    }

    gbTemperInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_AUTO_MODE_SUPPORT | INFO_SET_SUPPORT | INFO_GET_SUPPORT;
    gbEVInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_AUTO_MODE_SUPPORT | INFO_GET_SUPPORT | INFO_SET_SUPPORT;
    gbGainInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_GET_SUPPORT | INFO_SET_SUPPORT;
}

extern UVCX_VIDEO_CONFIG gsCurH264Config;
extern UVCX_VIDEO_CONFIG gsCurPreviewConfig;
extern UVCX_VIDEO_CONFIG gsUVCXVideoConfigProbe_Cur;

extern SKYPE_UVC_PROBE gsSkypeStreamFormat_Commit_Cur[2];
extern SKYPE_UVC_PROBE gsSkypeStreamFormat_Probe_Cur[2];

MMP_UBYTE SetH264Mode(MMP_UBYTE Mode)
{
    MMP_UBYTE OldMode;
#if SKYPE_MODE_B
    if(gbCurH264Type == SKYPE_H264){
        gbEnableH264Mode = Mode ;
        RTNA_DBG_Str0("Enable Skype.H264 mode:");
        RTNA_DBG_Byte0(gbEnableH264Mode);
        RTNA_DBG_Str0("\r\n");
    }
#else
    if(0){
    }
#endif
#if USB_MJPEGH264_STREAM
    else if(gbCurH264Type == UVC_H264){
        gbEnableH264Mode = Mode ;
        RTNA_DBG_Str3("Enable LGT.H264 mode:");
        RTNA_DBG_Byte3(gbEnableH264Mode);
        RTNA_DBG_Str3("\r\n");
    }
#endif
#if SKYPE_UVC_H264
    else if(gbCurH264Type == UVC_H264_STREAM){
        gbEnableH264Mode = Mode ;
        RTNA_DBG_Str3("Enable Skype UVC H.264 Stream mode:");
        RTNA_DBG_Byte3(gbEnableH264Mode);
        RTNA_DBG_Str3("\r\n");
    }
#endif
#if (SECS_VER > 0)
    else if(gbCurH264Type == SKYPE_TX_STREAM){
#if XU_FRAMEBASE_CAPTURE
        gFramebaseCap.SECS = MMP_TRUE;
#endif
        gbEnableH264Mode = Mode ;
        RTNA_DBG_Str3("Enable Skype Transport Stream mode:");
        RTNA_DBG_Byte3(gbEnableH264Mode);
        RTNA_DBG_Str3("\r\n");
    }
#endif        
    else{
        gbEnableH264Mode = Mode ;
    }

#if USB_UVC_BULK_EP
    //gbCheckSystemInitFlag = 1;
#endif    
    // sean@2010_10_04

    if(INVALID_H264 == gbEnableH264Mode){
        // gbCurH264Type = INVALID_H264  ;

        gbSkypeEncRes = 0;  // clear variable while video stop

#if SKYPE_UVC_H264
        gsCurH264Config.bStreamMuxOption = 0;
        gsCurH264Config.bTimestamp = 0;
        gsCurPreviewConfig.bStreamMuxOption = 0;
        gsUVCXVideoConfigProbe_Cur.bStreamMuxOption = 0;
#endif
#if (SECS_VER > 0)
        gsSkypeStreamFormat_Commit_Cur[0].bStreamType = 0;
#endif
    }
    OldMode = gbEnableH264Mode;
    return OldMode;
}

/*
static RES_TYPE_LIST  mjpg_frame_index_to_local_preview_index(MMP_UBYTE res_index)
{
    RES_TYPE_LIST res ;
    switch(res_index) {
        case 1:
        case 2:
        case 3:
        case 6:
        case 9:
        case 16:
            res = PCCAM_320_240;
            break;
        case 4:
        case 5:
        case 7:
        case 8:
        case 10:
        case 11:
        case 12:
        case 13:
        case 14:
        case 15:
        case 17:
        default:
            res = PCCAM_384_216;
            break;
    }    
    return res ;
}
*/

#define USE_UNIFIED_DESC_RES_FUNC 1
#if RES_REFERENCE_DESC && USE_UNIFIED_DESC_RES_FUNC
//Find a PCAM resolution from descriptor offset
static RES_TYPE_LIST uvc_frame_index_to_pcam(MMP_USHORT offset)
{
    RES_TYPE_LIST res = PCCAM_RES_NUM;

    MMP_UBYTE i = 0;
    MMP_UBYTE *pDesc;
    MMP_USHORT frame_width, frame_height;

#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor == MAIN_SENSOR){
        pDesc = (gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1);
    }
    else{
        pDesc = (gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA2 : CONFIG_DESCRIPTOR_DATA1);
    }
#else
    pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1;
#endif

    frame_width = (pDesc[offset + 0x06] << 8) | pDesc[offset + 0x05];
    frame_height = (pDesc[offset + 0x08] << 8) | pDesc[offset + 0x07];

    do{
        if((frame_width == gsCurResList[i].res_w) && (frame_height == gsCurResList[i].res_h)){
            res = gsCurResList[i].res_type;
            break;
        }
        i++;
    }
    while(gsCurResList[i].res_type != PCCAM_RES_NUM);
    return res;
}
#endif

#if ENABLE_YUY2
//TODO Try to merge with mjpg_frame_index_to_pcam
RES_TYPE_LIST yuy2_frame_index_to_pcam(MMP_UBYTE res_index)
{
#if USE_UNIFIED_DESC_RES_FUNC
#if SUPPORT_SWITCH_CAMERA
    return uvc_frame_index_to_pcam((gbSwitchSensor == MAIN_SENSOR) ?
                                   (S1_YUY2_FRAME_OFFSET + USB_UVC_S1_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1)) :
                                   (S2_YUY2_FRAME_OFFSET + USB_UVC_S2_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1)));
#else
    //SUPPORT_DUAL_DEVICE || others
    return uvc_frame_index_to_pcam((gbProbeCommitCamera ? D1_DESCRIPTOR_LEN : 0) +
                                   S1_YUY2_FRAME_OFFSET +
                                   USB_UVC_S1_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1));
#endif
#else
    RES_TYPE_LIST res = PCCAM_RES_NUM;

#if RES_REFERENCE_DESC
    MMP_UBYTE i = 0;
    MMP_UBYTE *pDesc;
    MMP_USHORT frame_width, frame_height, offset;

#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor == MAIN_SENSOR){
        pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1;
    }
    else{
        pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA2 : CONFIG_DESCRIPTOR_DATA1;
    }
#else
    pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1;
#endif

#if SUPPORT_SWITCH_CAMERA
    offset = (gbSwitchSensor == MAIN_SENSOR) ?
             (S1_YUY2_FRAME_OFFSET + USB_UVC_S1_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1)) :
             (S2_YUY2_FRAME_OFFSET + USB_UVC_S2_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1));
#else
    //SUPPORT_DUAL_DEVICE || others
    offset = (gbProbeCommitCamera ? D1_DESCRIPTOR_LEN : 0) +
             S1_YUY2_FRAME_OFFSET +
             USB_UVC_S1_IF_STREAM_FRAME_YUY2_DESC_SIZE * (res_index - 1);
#endif

    frame_width = (pDesc[offset + 0x06] << 8) | pDesc[offset + 0x05];
    frame_height = (pDesc[offset + 0x08] << 8) | pDesc[offset + 0x07];
    /*
    VAR_W(3, gbProbeCommitCamera);
    VAR_W(3, res_index);
    VAR_L(3, offset);
    VAR_W(3, frame_width);
    VAR_W(3, frame_height);
    */
    do{
        if((frame_width == gsCurResList[i].res_w) && (frame_height == gsCurResList[i].res_h)){
            res = gsCurResList[i].res_type;
            break;
        }
        i++;
    }
    while(gsCurResList[i].res_type != PCCAM_RES_NUM);
#else
    switch(res_index){
    case 1:
        //640x480
        if(gbUsbHighSpeed){
            res = PCCAM_640_480;
            //RTNA_DBG_Str(0, "640x480 SET \r\n");
        }
        else{
            res = PCCAM_160_120;
            //RTNA_DBG_Str(0, "160x120 SET \r\n");
        }
        break;
    case 2:
        //160x120
        //maxFrame = 160*120*2 ;
        if(gbUsbHighSpeed){
            res = PCCAM_160_120;
            //RTNA_DBG_Str(0, "160x120 SET \r\n");
        }
        else{
            res = PCCAM_640_480;
            //RTNA_DBG_Str(0, "640x480 SET \r\n");
        }
        break;
    case 3:
        //320x240
        res = PCCAM_320_240;
        //RTNA_DBG_Str(0, "320x240 SET \r\n");
        break;
    case 4:
        //640x360
        res = PCCAM_640_360;
        //RTNA_DBG_Str(0, "640x360 SET \r\n");
        break;
    case 5:
        //384x216
        res = PCCAM_384_216;
        //RTNA_DBG_Str(0, "384x216 SET \r\n");
        break;
    case 6:
        //352x288
        //RTNA_DBG_Str(0, "352x288 SET \r\n");
        res = PCCAM_352_288;
        break;
    case 7:
        //RTNA_DBG_Str(0, "1280x720 SET \r\n");
        res = PCCAM_1280_720;
        break;    
    case 8:
        //RTNA_DBG_Str(0, "960x720 SET \r\n");
        res = PCCAM_960_720;
        break;    
    case 9:
        //RTNA_DBG_Str(0, "800x448 SET \r\n");
        res = PCCAM_800_448;
        break;    
    case 10:
        //RTNA_DBG_Str(0, "800x600 SET \r\n");
        res = PCCAM_800_600;
        break;    
    case 11:
        //RTNA_DBG_Str(0, "160x90 SET \r\n");
        res = PCCAM_160_90;
        break;    
    case 12:
        //RTNA_DBG_Str(0, "320x180 SET \r\n");
        res = PCCAM_320_180;
        break;    
#if (USB_UVC_1080P_YUY2_EN)
    case 13:
        res = PCCAM_1920_1080;
        break;    
#endif
#if (USB_UVC_5M_EN)
    case 14:
        res = PCCAM_1024_768;
        break;    
    case 15:
        res = PCCAM_1600_1200;
        break;    
    case 16:
        res = PCCAM_2048_1536;
        break;    
    case 17:
        res = PCCAM_2592_1944;
        break;
#endif
    }
    #endif //#if RES_REFERENCE_DESC
    return res ;
#endif //#if USE_UNIFIED_DESC_RES_FUNC
}
#endif //#if ENABLE_YUY2

#if ENABLE_MJPEG
RES_TYPE_LIST mjpg_frame_index_to_pcam(MMP_UBYTE res_index)
{
#if USE_UNIFIED_DESC_RES_FUNC
#if SUPPORT_SWITCH_CAMERA
    return uvc_frame_index_to_pcam((gbSwitchSensor == MAIN_SENSOR) ?
                                   (S1_MJPEG_FRAME_OFFSET +
                                    USB_UVC_S1_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1)) :
                                   (S2_MJPEG_FRAME_OFFSET +
                                    USB_UVC_S2_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1)));
#else
    //SUPPORT_DUAL_DEVICE || others
    return uvc_frame_index_to_pcam((gbProbeCommitCamera ? D1_DESCRIPTOR_LEN : 0) +
                                   S1_MJPEG_FRAME_OFFSET +
                                   USB_UVC_S1_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1));
#endif
#else
    RES_TYPE_LIST res = PCCAM_RES_NUM;

#if RES_REFERENCE_DESC
    MMP_UBYTE i = 0;
    MMP_UBYTE *pDesc;
    MMP_USHORT frame_width, frame_height;
    MMP_ULONG offset;

#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor == MAIN_SENSOR){
        pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1;
    }
    else{
        pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA2 : CONFIG_DESCRIPTOR_DATA1;
    }
#else
    pDesc = gbUsbHighSpeed ? HS_CONFIG_DESCRIPTOR_DATA1 : CONFIG_DESCRIPTOR_DATA1;
#endif

#if SUPPORT_SWITCH_CAMERA
    offset = (gbSwitchSensor == MAIN_SENSOR) ?
             (S1_MJPEG_FRAME_OFFSET + USB_UVC_S1_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1)) :
             (S2_MJPEG_FRAME_OFFSET + USB_UVC_S2_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1));
#else
    //SUPPORT_DUAL_DEVICE || others
    offset = (gbProbeCommitCamera ? D1_DESCRIPTOR_LEN : 0) +
             S1_MJPEG_FRAME_OFFSET +
             USB_UVC_S1_IF_STREAM_FRAME_MJPEG_DESC_SIZE * (res_index - 1);
#endif

    frame_width = (pDesc[offset + 0x06] << 8) | pDesc[offset + 0x05];
    frame_height = (pDesc[offset + 0x08] << 8) | pDesc[offset + 0x07];
    /*
    VAR_W(3, gbProbeCommitCamera);
    VAR_W(3, res_index);
    VAR_L(3, offset);
    VAR_W(3, frame_width);
    VAR_W(3, frame_height);
       */
    do{
        if((frame_width == gsCurResList[i].res_w) && (frame_height == gsCurResList[i].res_h)){
            res = gsCurResList[i].res_type;
            break;
        }
        i++;
    }
    while(gsCurResList[i].res_type != PCCAM_RES_NUM);
#else
    switch(res_index){
    case 1:
        if(gbUsbHighSpeed){
            //RTNA_DBG_Str(0, "1280x720 SET \r\n");
            res = PCCAM_1280_720;
        }
        else{
            res = PCCAM_160_120;
        }
        break;    
    case 2:
        //160x120
        if(gbUsbHighSpeed){
            //RTNA_DBG_Str(0, "1280x720 SET \r\n");
            res = PCCAM_160_120;
        }
        else{
            res = PCCAM_1280_720;
        }
        break;
    case 3:
        //320x240
        res = PCCAM_320_240;
        //RTNA_DBG_Str(0, "320x240 SET \r\n");
        break;
    case 4:
        //640x360
        res = PCCAM_640_360;
        //RTNA_DBG_Str(0, "640x360 SET \r\n");
        break;
    case 5:
        //384x216
        res = PCCAM_384_216;
        //RTNA_DBG_Str(0, "384x216 SET \r\n");
        break;
    case 6:
        //352x288
        //RTNA_DBG_Str(0, "352x288 SET \r\n");
        res = PCCAM_352_288;
        break;
    case 7:
        //640x480
        res = PCCAM_640_480;
        //RTNA_DBG_Str(0, "640x480 SET \r\n");
        break;
    case 8:
        //RTNA_DBG_Str(0, "960x720 SET \r\n");
        res = PCCAM_960_720;
        break;    
    case 9:
        //RTNA_DBG_Str(0, "1024x576 SET \r\n");
        res = PCCAM_1024_576;//PCCAM_1024_768;
        break;    
    case 10:
        //RTNA_DBG_Str(0, "800x448 SET \r\n");
        res = PCCAM_800_448;
        break;    
    case 11:
        //RTNA_DBG_Str(0, "800x600 SET \r\n");
        res = PCCAM_800_600;
        break;    
    case 12:
        //RTNA_DBG_Str(0, "160x90 SET \r\n");
        res = PCCAM_160_90;
        break;    
    case 13:
        //RTNA_DBG_Str(0, "320x180 SET \r\n");
        res = PCCAM_320_180;
        break;    
    case 14:
        //RTNA_DBG_Str(0, "480x270 SET \r\n");
        res = PCCAM_480_270;
        break;
    case 15:
        //RTNA_DBG_Str(0, "800x450 SET \r\n");
        res = PCCAM_800_450;
        break;
#if USB_UVC_1080P_MJPEG_EN
    case 16:
        res = PCCAM_1920_1080;
        break;    
#endif
#if (USB_UVC_5M_EN)
    case 17:
        res = PCCAM_1280_960;
        break;    
    case 18:
        res = PCCAM_1600_1200;
        break;    
    case 19:
        res = PCCAM_2048_1536;
        break;    
    case 20:
        res = PCCAM_2592_1944;
        break;    
#endif
#if (CUSTOMER == QDR) && BIND_SENSOR_AR0330
    case 21:
        //RTNA_DBG_Str(0, "2304x1296 SET \r\n");
        res = PCCAM_2304_1296;
        break;
#endif
    }
#endif
    return res ;
#endif
}
#endif

#if ENABLE_FRAME_BASE_H264
static RES_TYPE_LIST h264_frame_index_to_pcam(MMP_UBYTE res_index)
{
    RES_TYPE_LIST res ;

    switch(res_index){
    case 1:
        res = PCCAM_1280_720;
        //RTNA_DBG_Str(0, "1280x720 SET \r\n");
        break;    
    case 2:
        //640x480
        res = PCCAM_640_480;
        //RTNA_DBG_Str(0, "640x480 SET \r\n");
        break;
    case 3:
        //320x240
        res = PCCAM_320_240;
        //RTNA_DBG_Str(0, "320x240 SET \r\n");
        break;
    case 4:
        //160x120
        res = PCCAM_160_120;
        //RTNA_DBG_Str(0, "160x120 SET \r\n");
        break;
    case 5:
        res = PCCAM_160_90;
        //RTNA_DBG_Str(0, "160x90 SET \r\n");
        break;    
    case 6:
        res = PCCAM_320_180;
        //RTNA_DBG_Str(0, "320x180 SET \r\n");
        break;    
    case 7:
        res = PCCAM_640_360;
        //RTNA_DBG_Str(0, "640x360 SET \r\n");
        break;    
    case 8:
        res = PCCAM_480_270;
        //RTNA_DBG_Str(0, "480x270 SET \r\n");
        break;
    case 9:
        res = PCCAM_800_450;
        //RTNA_DBG_Str(0, "800x450 SET \r\n");
        break;
    case 10:
        res = PCCAM_1024_576;
        //RTNA_DBG_Str(0, "1024x576 SET \r\n");
        break;
#if USB_UVC_1080P_EN
    case 11:
        res = PCCAM_1920_1080;
        //RTNA_DBG_Str(0, "1920x1080 SET \r\n");
        break;    
#endif
    }
    return res ;
}
#endif

void usb_uvc_set_h264_mode(MMP_UBYTE FormatIndex, MMP_UBYTE FrameIndex)
{
    // PCAM_USB_VIDEO_RES pCamRes ;
#if 1
RTNA_DBG_Str(0, "  ** gbEnableH264Mode = ");
RTNA_DBG_Byte(0, gbEnableH264Mode);
RTNA_DBG_Str(0, "\r\n");
RTNA_DBG_Str(0, "  ** FormatIndex = ");
RTNA_DBG_Byte(0, FormatIndex);
RTNA_DBG_Str(0, "\r\n");
RTNA_DBG_Str(0, "  ** FrameIndex = ");
RTNA_DBG_Byte(0, FrameIndex);
RTNA_DBG_Str(0, "\r\n");
#endif
    if(gbEnableH264Mode > 0){
#if ENABLE_FRAME_BASE_H264
        PCAM_USB_VIDEO_RES h264Res ;
#endif

        switch(FormatIndex){
#if ENABLE_YUY2
        case YUY2_FORMAT_INDEX:
            //YVY2
#endif
#ifdef ENABLE_UYVY
        case UYVY_FORMAT_INDEX:
            //YVY2
#endif

            switch(FrameIndex){
            case 1:
#if SKYPE_MODE_B
                glPccamResolution = skype_yuy2_to_pcam(gbEnableH264Mode);
                h264Res = skype_h264_to_pcam(gbEnableH264Mode);
                USB_SetH264Resolution(PCAM_API, h264Res);
#else
                dbg_printf(3, "[ERR]frame_idx %d\r\n", FrameIndex);
#endif          
                break;
            }  // end of switch(FrameIndex)
            break;

#if ENABLE_MJPEG
            //#if USB_UVC_H264
        case MJPEG_FORMAT_INDEX:
             {
#if USB_MJPEGH264_STREAM
                if(gbSkypeEncRes){
                    //glPccamResolution = mjpg_frame_index_to_local_preview_index(FrameIndex);
                    glPccamResolution = skype_yuy2_to_pcam(gbSkypeEncRes);
                    h264Res = skype_h264_to_pcam(gbSkypeEncRes);
                    USB_SetH264Resolution(PCAM_API, h264Res);
                }
#else
                if(0){
                }
#endif
#if (SECS_VER > 0)
                else if(gsSkypeStreamFormat_Commit_Cur[0].bStreamType == SKYPE_FORMAT_H264){
                    glPccamResolution = GetSkypePreviewResIndex(gsSkypeStreamFormat_Commit_Cur[1].wWidth,
                                                                gsSkypeStreamFormat_Commit_Cur[1].wHeight);
                    h264Res = GetSkypeMainResIndex(gsSkypeStreamFormat_Commit_Cur[0].wWidth,
                                                   gsSkypeStreamFormat_Commit_Cur[0].wHeight);
                    USB_SetH264Resolution(PCAM_API, h264Res);
                }
#endif
#if SKYPE_UVC_H264
                else if(gsCurH264Config.bStreamMuxOption & DUAL_AUX_H264){
                    glPccamResolution = GetSkypePreviewResIndex(gsCurPreviewConfig.wWidth, gsCurPreviewConfig.wHeight);
                    h264Res = GetSkypeMainResIndex(gsCurH264Config.wWidth, gsCurH264Config.wHeight);
                    USB_SetH264Resolution(PCAM_API, h264Res);
                }
#endif
                else{
                    // non H.264 mode
                    glPccamResolution = mjpg_frame_index_to_pcam(FrameIndex);
                }
            }
            break;                
#endif                        

#if ENABLE_FRAME_BASE_H264
            //#if USB_UVC_H264
        case FRAME_BASE_H264_INDEX:
             {
                h264Res = h264_frame_index_to_pcam(FrameIndex);
                USB_SetH264Resolution(PCAM_API, h264Res);
#if USB_FRAMEBASE_H264_YUY2_STREAM
                if((h264Res == PCCAM_1280_720) || (h264Res == PCCAM_1920_1080))
                    glPccamResolution = PCCAM_640_480; //PCCAM_384_216;
                else
                    glPccamResolution = PCCAM_640_480; //PCCAM_320_240
#else
                glPccamResolution = h264_frame_index_to_pcam(FrameIndex);
#endif
            }
            break;                
            //#endif                        
#endif     

        default:
            break;
        }  // end of switch(FormatIndex)
    }  // end of if(gbEnableH264Mode>0)
}

#if SKYPE_MODE_B || USB_MJPEGH264_STREAM
static RES_TYPE_LIST skype_yuy2_to_pcam(MMP_UBYTE skype_res_index)
{
    RES_TYPE_LIST res ;
    switch(skype_res_index){
    case 1:
    case 2:
    case 3:
    case 4:
    case 12:
    case 15:
        res = PCCAM_320_240;
        break;
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
    case 11:
    case 13:
    case 14:
    case 16:
    default:
        res = PCCAM_384_216;
        break;
    }    
    return res ;
}

static PCAM_USB_VIDEO_RES skype_h264_to_pcam(MMP_UBYTE skype_res_index)
{
    H264_ENCODER_VFC_CFG *cur_cfg = usb_get_uvc_h264_cfg();

    PCAM_USB_VIDEO_RES res ;
    switch(skype_res_index){
    case 1:
        res = PCAM_USB_RESOL_160x120 ;
        cur_cfg->wWidth = 160 ;
        cur_cfg->wHeight = 120 ;
        break;
    case 2:
        res = PCAM_USB_RESOL_320x240;
        cur_cfg->wWidth = 320 ;
        cur_cfg->wHeight = 240 ;
        break;
    case 3:
        res = PCAM_USB_RESOL_640x480;
        cur_cfg->wWidth = 640 ;
        cur_cfg->wHeight = 480 ;
        break;
    case 4:
        res = PCAM_USB_RESOL_960x720 ;
        cur_cfg->wWidth = 960 ;
        cur_cfg->wHeight = 720 ;
        break;
    case 5:
        res = PCAM_USB_RESOL_272x144 ;
        cur_cfg->wWidth = 272 ;
        cur_cfg->wHeight = 144 ;
        break;
    case 6:
        res = PCAM_USB_RESOL_368x208 ;
        cur_cfg->wWidth = 368 ;
        cur_cfg->wHeight = 208 ;
        break;
    case 7:
        res = PCAM_USB_RESOL_480x272 ;
        cur_cfg->wWidth = 480 ;
        cur_cfg->wHeight = 272 ;
        break;
    case 8:
        res = PCAM_USB_RESOL_624x352 ;
        cur_cfg->wWidth = 624 ;
        cur_cfg->wHeight = 352 ;
        break;
    case 9:
        res = PCAM_USB_RESOL_912x512 ;
        cur_cfg->wWidth = 912 ;
        cur_cfg->wHeight = 512 ;
        break;
    case 10:
        res = PCAM_USB_RESOL_1280x720 ;
        cur_cfg->wWidth = 1280 ;
        cur_cfg->wHeight = 720 ;
        break;
    case 11:
        res = PCAM_USB_RESOL_1920x1080 ;
        cur_cfg->wWidth = 1920 ;
        cur_cfg->wHeight = 1088 ;
        break;
    case 12:
        res = PCAM_USB_RESOL_352x288 ;
        cur_cfg->wWidth = 352 ;
        cur_cfg->wHeight = 288 ;
        break;
    case 13:
        res = PCAM_USB_RESOL_640x360 ;
        cur_cfg->wWidth = 640 ;
        cur_cfg->wHeight = 360 ;
        break;
    case 14:
        res = PCAM_USB_RESOL_800x448 ;
        cur_cfg->wWidth = 800 ;
        cur_cfg->wHeight = 448 ;
        break;
    case 15:
        res = PCAM_USB_RESOL_800x600 ;
        cur_cfg->wWidth = 800 ;
        cur_cfg->wHeight = 600 ;
        break;
    case 16:
        res = PCAM_USB_RESOL_960x544 ;
        cur_cfg->wWidth = 960 ;
        cur_cfg->wHeight = 544 ;
        break;
    case 17:
        res = PCAM_USB_RESOL_160x90 ;
        cur_cfg->wWidth = 160 ;
        cur_cfg->wHeight = 90 ;
        break;
    case 18:
        res = PCAM_USB_RESOL_320x180 ;
        cur_cfg->wWidth = 320 ;
        cur_cfg->wHeight = 180 ;
        break;
    default:
        res = PCAM_USB_RESOL_1280x720 ;
        cur_cfg->wWidth = 1280 ;
        cur_cfg->wHeight = 720 ;
        break;
    }   
    return res ;
}

#endif

void usb_vc_cfg_video_probe(MMP_UBYTE format_idx, MMP_UBYTE frame_idx, MMP_ULONG max_frame_size,
                            MMP_ULONG max_payload_size)
{
    vp.bFormatIndex = format_idx;
    vp.bFrameIndex = frame_idx;
    vp.dwMaxFrameSize = max_frame_size;
    vp.dwMaxPayloadSize = max_payload_size;
}

void usb_vc_get_video_probe(MMP_UBYTE FormatIndex, MMP_UBYTE FrameIndex, MMP_BOOL upd)
{
    //MMP_USHORT index = 0;
    MMP_ULONG  maxFrame = 0,maxPayload = 0;
    PCAM_USB_VIDEO_FORMAT   pCamVidFmt;
    RES_TYPE_LIST           pCamRes = 0;
    MMP_UBYTE               lmode;

    lmode = FrameIndex;//mode;
    #if (USB_UVC_BULK_EP)
    maxPayload = TX_PER_FRAME * HS_TX_MAX_PK_SIZE;
    #else
    maxPayload = UVCTxFIFOSize;
    #endif

    //index = (FrameIndex<<8) + FormatIndex ;
#if ENABLE_YUY2
    if(FormatIndex == (YUY2_FORMAT_INDEX)){
#if (RAW_PREVIEW_ENABLE && RAW_PREVIEW_USING_YUY2_PAYLOAD)
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_RAW ;
#else    
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_YUV422 ;
#endif        
        //RTNA_DBG_Str(0, "   [YUY2 Order]\r\n");
    #if SKYPE_MODE_B
        if(gbSkypeMode == 2){
            gbCurH264Type = SKYPE_H264 ; // OOXX test
            if(gbCurH264Type == SKYPE_H264){
                //RTNA_DBG_Str(0, "   [Skype ModeB Order,H264]\r\n");
            }
        }
        else
    #endif
        {
            gbCurH264Type = INVALID_H264 ; // OOXX test
        }
    }

#endif
#if defined(ENABLE_UYVY)
    if(FormatIndex == (UYVY_FORMAT_INDEX)){
        //RTNA_DBG_Str(0, "   [UYVY Order]\r\n");
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_YUV422 ;
    }
#endif
#ifdef ENABLE_NV12
    if(FormatIndex == (NV12_FORMAT_INDEX)){
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_YUV420 ;
    }
#endif
#if ENABLE_MJPEG
    if(FormatIndex == (MJPEG_FORMAT_INDEX)){
#if USB_MJPEGH264_STREAM
        if(gbSkypeEncRes){
            gbCurH264Type = UVC_H264;
            if(gbCurH264Type == UVC_H264){
                //RTNA_DBG_Str(0, "   [MJPEG Order,H264]\r\n");
            }
        }
        else{
            gbCurH264Type = INVALID_H264;
        }
#endif        
#if (SECS_VER > 0)
        if(gsSkypeStreamFormat_Commit_Cur[0].bStreamType == SKYPE_FORMAT_H264){
            gbCurH264Type = SKYPE_TX_STREAM ; // OOXX test
            if(gbCurH264Type == SKYPE_TX_STREAM){
                RTNA_DBG_Str(0, "   [Skype Transport Stream,H264]\r\n");
            }
        }
#endif        
#if SKYPE_UVC_H264==1
        //RTNA_DBG_Str(0, "  gsCurH264Config.bStreamMuxOption = ");       
        //RTNA_DBG_Short(0, gsCurH264Config.bStreamMuxOption);
        //RTNA_DBG_Str(0, "\r\n");
        if(gsCurH264Config.bStreamMuxOption & DUAL_AUX_H264){
            gbCurH264Type = UVC_H264_STREAM ; // OOXX test
            //RTNA_DBG_Str(0, "   [Skype UVC H.264 Stream,H264]\r\n");
        }
#endif
#if (RAW_PREVIEW_ENABLE && RAW_PREVIEW_USING_MJPEG_PAYLOAD)
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_RAW ;
#else    
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_MJPEG ;
#endif
    }
#endif
#if ENABLE_FRAME_BASE_H264
    if(FormatIndex == (FRAME_BASE_H264_INDEX)){
        pCamVidFmt = PCAM_USB_VIDEO_FORMAT_H264 ;
        //Vin: Dual H264 option 
        /*
        #if USB_FRAMEBASE_H264_YUY2_STREAM
                gbCurH264Type = FRAMEBASE_H264_YUY2 ;
                //RTNA_DBG_Str(0, "   [Frame Base + YUY2 Order,H264]\r\n");
        #elif USB_FRAMEBASE_DUAL_H264_STREAM
                gbCurH264Type = FRAMEBASE_DUAL_H264 ;
                //RTNA_DBG_Str(0, "   [Frame Base Dual H264 Order]\r\n");
        #elif USB_FRAMEBASE_H264_MJPEG_STREAM
                gbCurH264Type = FRAMEBASE_H264_MJPEG;
        #else
                gbCurH264Type = FRAMEBASE_H264 ;
                //RTNA_DBG_Str(0, "   [Frame Base Order,H264]\r\n");
        #endif        
        */
        //It should be set by XU
        if(gbSkypeMode == 0x86){
            gbCurH264Type = FRAMEBASE_DUAL_H264_MJPEG;//FRAMEBASE_DUAL_H264;
        }
        else if(gbSkypeMode == 0x88){
            gbCurH264Type = FRAMEBASE_H264RT_MJPEG;
        }
        else if(gbSkypeMode == 0x89){
#if RAW_DATA_EN
            extern MMP_USHORT gsFrameDataWithRaw ;
            gsFrameDataWithRaw = 1;
#endif
            gbCurH264Type = FRAMEBASE_H264FRAME_MJPEG;
        }
        else if(gbSkypeMode == 0x8A){
#if RAW_DATA_EN
            extern MMP_USHORT gsFrameDataWithRaw ;
            gsFrameDataWithRaw = 1;
#endif
            gbCurH264Type = FRAMEBASE_DUAL_H264_MJPEG;
        }
        else{
            gbCurH264Type = FRAMEBASE_H264;
        }
    }

#endif

    switch(FormatIndex){
#if (ENABLE_YUY2) || defined(ENABLE_UYVY)

#if (ENABLE_YUY2)
    case YUY2_FORMAT_INDEX:
        //YVY2
#endif

        pCamRes = yuy2_frame_index_to_pcam(FrameIndex);   

        maxFrame = GetYUY2FrameSize((MMP_UBYTE) pCamRes);

        break;
#endif

#if ENABLE_MJPEG
    case MJPEG_FORMAT_INDEX:
        //MJPEG
         {
#if FRAME_SIZE_NEW_PLAN
            MMP_ULONG fw_end;

            MMPF_SYS_GetFWEndAddr(&fw_end);
#endif
            pCamRes = mjpg_frame_index_to_pcam(FrameIndex);

#if RAW_PREVIEW_ENABLE
            maxFrame = 0x00800000;//0x00280000 ;
#else

#if 0//FRAME_SIZE_NEW_PLAN  //Mark for QDR
        maxFrame = ((MAX_DRAM_BUF_ADDR - fw_end - VP_PLAN_SIZE) >> 1);
#else
        maxFrame = GetMJPEGFrameSize((MMP_UBYTE)pCamRes);
#endif

            //Truman@120926 patch for UVC1.1
            if(INVALID_H264 != gbCurH264Type){
                RES_TYPE_CFG *cur_res;
#if SKYPE_UVC_H264
                if(UVC_H264_STREAM == gbCurH264Type){
                    maxFrame += gsCurPreviewConfig.wWidth * gsCurPreviewConfig.wHeight * 2; //+ preview YUY2 size
                    dbg_printf(3, "UVC11");
                }
#else
                if(0){
                }
#endif
#if (SECS_VER > 20)
                else if(SKYPE_TX_STREAM == gbCurH264Type){
                    if(gsSkypeStreamFormat_Probe_Cur[1].bStreamType == SKYPE_FORMAT_YUY2){
                        maxFrame += gsSkypeStreamFormat_Probe_Cur[1].wWidth * gsSkypeStreamFormat_Probe_Cur[1].wHeight * 2; //+ preview YUY2 size
                        //dbg_printf(3, "R & W & H: %x %x %x \r\n", glPccamResolution, gsSkypeStreamFormat_Probe_Cur[1].wWidth, gsSkypeStreamFormat_Probe_Cur[1].wHeight);
                    }
                    dbg_printf(3, "Skype TX");
                }
#endif
                else{
                    cur_res = GetResCfg(pCamRes);
                    maxFrame += cur_res->res_h * cur_res->res_w / 2;//up to 25% YUY2 size. e.g VGA;
                    dbg_printf(3, "H264 in MJPEG");
                }
                dbg_printf(3, " max frame size: %d\r\n", maxFrame);
            }
    #endif //#if RAW_PREVIEW_ENABLE
        }
        break;
#endif //#if ENABLE_MJPEG

#if ENABLE_FRAME_BASE_H264
    case    FRAME_BASE_H264_INDEX:
        pCamRes = h264_frame_index_to_pcam(FrameIndex);

#if USB_FRAMEBASE_H264_YUY2_STREAM
        //            maxFrame = GetH264FrameSize((MMP_UBYTE)pCamRes) + 0xA0000;  // for H264 + YUY2 VGA
        maxFrame = 0x100000;  // for H264 + YUY2 VGA
#elif USB_FRAMEBASE_DUAL_H264_STREAM
        maxFrame = 0x100000;  // for H264 + H264 720x480
#else
#if XU_FRAMEBASE_CAPTURE
        if(gFramebaseCap.format == CF_YUY2/*1*/){
            maxFrame = GetYUY2FrameSize((MMP_UBYTE) pCamRes) + FRAME_PAYLOAD_HEADER_SZ;
        }
        else if(gFramebaseCap.format == CF_MJPEG/*2*/){
            MMP_ULONG fw_end;
            MMPF_SYS_GetFWEndAddr(&fw_end);
            maxFrame = ((MAX_DRAM_BUF_ADDR - fw_end - VP_PLAN_SIZE) >> 1);
        }
        else
                #endif
        {
            maxFrame = GetH264FrameSize((MMP_UBYTE) pCamRes);
        }
#endif //#if USB_FRAMEBASE_H264_YUY2_STREAM

        break; 
#endif //#if ENABLE_FRAME_BASE_H264
    }

#if 0//XU_FRAMEBASE_CAPTURE
    maxFrame = 1280*720*2+32;
#endif

    usb_vc_cfg_video_probe(FormatIndex, FrameIndex, maxFrame, maxPayload);

    //    if(upd) {    
    if(upd && (gbUVCStartPreviewFlagSet == FALSE)){
        USB_SetVideoFormat(PCAM_API/*PCAM_NONBLOCKING*/, pCamVidFmt) ;
        glPccamResolution = pCamRes ;
    }
}

/*
void usb_vc_get_commit(STILL_PROBE* pSC)
{
    pSC->bFormatIndex = sc.bFormatIndex;
    pSC->bFrameIndex = sc.bFrameIndex;
    pSC->bCompressIndex = sc.bCompressIndex;
    pSC->bMaxFrameSize[0] = sc.bMaxFrameSize[0];
    pSC->bMaxFrameSize[1] = sc.bMaxFrameSize[1];
    pSC->bMaxFrameSize[2] = sc.bMaxFrameSize[2];
    pSC->bMaxFrameSize[3] = sc.bMaxFrameSize[3];    
    pSC->bMaxPayloadSize[0] = sc.bMaxPayloadSize[0];
    pSC->bMaxPayloadSize[1] = sc.bMaxPayloadSize[1];
    pSC->bMaxPayloadSize[2] = sc.bMaxPayloadSize[2];
    pSC->bMaxPayloadSize[3] = sc.bMaxPayloadSize[3];    
}
*/
#if (USING_STILL_METHOD_1 == 0)

__inline void usb_vc_set_still_commit(STILL_PROBE *pSCIN)
{
    //RTNA_DBG_Str(0, "usb_vc_set_still_commit \r\n");
    sc = *pSCIN ;
}

void usb_vc_get_still_probe(MMP_UBYTE FormatIndex, MMP_UBYTE FrameIndex, STILL_PROBE *pSP)
{
    MMP_ULONG maxFrame ;
    MMP_ULONG maxPayload ;
    //RTNA_DBG_Str(0, "usb_vc_get_still_probe : ");

#if ENABLE_MJPEG
    if(FormatIndex == (MJPEG_FORMAT_INDEX)){
#if (CAPTURE_BAYER_RAW_ENABLE)
        maxFrame = 0x00280000 ;
#else
        maxFrame = 0x00140000 ;
#endif  

    #if (USB_UVC_BULK_EP)
        maxPayload = TX_PER_FRAME * HS_TX_MAX_PK_SIZE;
    #else
        maxPayload = UVCTxFIFOSize;
    #endif
        // RTNA_DBG_Str(0, "[MJPEG Order]\r\n");
    }
#endif

#ifdef ENABLE_UYVY
    if(FormatIndex == UYVY_FORMAT_INDEX){
        RTNA_DBG_Str(0, "[UYVY Order]\r\n");
    }
#endif

    switch(FormatIndex){
#if ENABLE_MJPEG
    case MJPEG_FORMAT_INDEX:
        DBG_S(2, "  ** JPEG ");
        switch(FrameIndex){
#if BIND_SENSOR_AR0832E
        case 1:
            // JPEG 2592x1944
            DBG_S(2, "2592x1944\r\n");
            break;

        case 2:
            // JPEG 2048x1536
            DBG_S(2, "2048x1536\r\n");
            break;

        case 3:
            // JPEG 1920x1080
            DBG_S(2, "1920x1080\r\n");
            break;

        case 4:
            // JPEG 1280x960
            DBG_S(2, "1280x960\r\n");
            break;

        case 5:
            // JPEG 1280x720
            DBG_S(2, "1280x720\r\n");
            break;

        case 6:
            // JPEG 640x480
            DBG_S(2, "640x480\r\n");
            break;
#else
        case 1:
            // JPEG 1280x720
            DBG_S(2, "1280x720\r\n");
            break;

        case 2:
            // JPEG 640x480
            DBG_S(2, "640x480\r\n");
            break;

        case 3:
            // JPEG 640x360
            DBG_S(2, "640x360\r\n");
            break;

        case 4:
            // JPEG 320x240
            DBG_S(2, "320x240\r\n");
            break;

        case 5:
            // JPEG 320x180
            DBG_S(2, "320x180\r\n");
            break;

        case 6:
            // JPEG 160x120
            DBG_S(2, "160x120\r\n");
            break;

        case 7:
            // JPEG 160x90
            DBG_S(2, "160x90\r\n");
            break;
#if BIND_SENSOR_AR0330
        case 8:
            // JPEG 1920x1080
            DBG_S(2, "1920x1080\r\n");
            break;

        case 9:
            // JPEG 2304x1296
            DBG_S(2, "2304x1296\r\n");
            break;
#endif
#endif
        default:
            break;
        }
        break;
#endif

#if (ENABLE_YUY2) || defined( ENABLE_UYVY )

#if ENABLE_YUY2
    case YUY2_FORMAT_INDEX:
#endif

#if defined(ENABLE_UYVY)
    case UYVY_FORMAT_INDEX:
#endif
        DBG_S(2, "  ** YUY2 ");
        switch(FrameIndex){
        case 1:
            // YUY2 640x480
            DBG_S(2, "640x480\r\n");
            maxFrame = 640 * 480 * 2 ;
            break;      

        case 2:
            // YUY2 320x240
            DBG_S(2, "320x240\r\n");
            maxFrame = 320 * 240 * 2 ;
            break;

        case 3:
            // YUY2 160x120
            DBG_S(2, "160x120\r\n");
            maxFrame = 160 * 120 * 2 ;
            break;

        default:
            dbg_printf(3, "unknown frame_index %d\r\n", FrameIndex);
            break;
        }
        break;
#endif
    default:
        break;
    }
    pSP->bFormatIndex = FormatIndex;
    pSP->bFrameIndex = FrameIndex;
    pSP->dwMaxFrameSize = maxFrame;
    pSP->dwMaxPayloadSize = maxPayload;
}

//void usb_vc_set_still_probe(STILL_PROBE* pSPIN)
void usb_vc_set_still_probe(MMP_UBYTE FormatIndex, MMP_UBYTE FrameIndex)
{
    //RTNA_DBG_Str(0, "usb_vc_set_still_probe \r\n");
    /*
    sp.bFormatIndex = pSPIN->bFormatIndex;
    sp.bFrameIndex = pSPIN->bFrameIndex;
    sp.bCompressIndex = pSPIN->bCompressIndex;
    sp.bMaxFrameSize[0] = pSPIN->bMaxFrameSize[0];
    sp.bMaxFrameSize[1] = pSPIN->bMaxFrameSize[1];
    sp.bMaxFrameSize[2] = pSPIN->bMaxFrameSize[2];
    sp.bMaxFrameSize[3] = pSPIN->bMaxFrameSize[3];  
    sp.bMaxPayloadSize[0] = pSPIN->bMaxPayloadSize[0];
    sp.bMaxPayloadSize[1] = pSPIN->bMaxPayloadSize[1];
    sp.bMaxPayloadSize[2] = pSPIN->bMaxPayloadSize[2];
    sp.bMaxPayloadSize[3] = pSPIN->bMaxPayloadSize[3];  
    */
    usb_vc_get_still_probe(FormatIndex, FrameIndex, &sp);
}


void usb_vc_set_still_resolution(MMP_UBYTE FormatIndex, MMP_UBYTE FrameIndex)
{
    // PCAM_USB_VIDEO_FORMAT pCamVidFmt;

    switch(FormatIndex){
#if ENABLE_YUY2
    case YUY2_FORMAT_INDEX:
        //m_VideoFmt = MMPS_3GPRECD_VIDEO_FORMAT_YUV422;
        //pCamVidFmt = PCAM_USB_VIDEO_FORMAT_YUV422 ;
        //              USB_SetVideoFormat(PCAM_NONBLOCKING,PCAM_USB_VIDEO_FORMAT_YUV422 );
        USB_SetVideoFormat(PCAM_API, PCAM_USB_VIDEO_FORMAT_YUV422);
        RTNA_DBG_Str(0, " ** Still Format is YUV422\r\n"); 
        switch(FrameIndex){
        case 1:
            //640x480
            glPccamResolution = PCCAM_640_480;  
            RTNA_DBG_Str(0, " ** Still Resolution is 640x480\r\n"); 
            break;
        case 2:
            //320x240
            glPccamResolution = PCCAM_320_240;  
            RTNA_DBG_Str(0, " ** Still Resolution is 320x240\r\n"); 
            break;
        case 3:
            //160x120
            glPccamResolution = PCCAM_160_120;
            RTNA_DBG_Str(0, " ** Still Resolution is 160x120\r\n"); 
            break;
        }   
        break;
#endif

#ifdef ENABLE_UYVY
    case UYVY_FORMAT_INDEX:
        //m_VideoFmt = MMPS_3GPRECD_VIDEO_FORMAT_YUV422;
        //pCamVidFmt = PCAM_USB_VIDEO_FORMAT_YUV422 ;
        //              USB_SetVideoFormat(PCAM_NONBLOCKING,PCAM_USB_VIDEO_FORMAT_YUV422 );
        USB_SetVideoFormat(PCAM_API, PCAM_USB_VIDEO_FORMAT_YUV422);
        RTNA_DBG_Str(0, " ** Still Format is YUV422\r\n"); 
        switch(FrameIndex){
        case 1:
            //640x480
            glPccamResolution = PCCAM_640_480;  
            RTNA_DBG_Str(0, " ** Still Resolution is 640x480\r\n"); 
            break;
        case 2:
            //320x240
            glPccamResolution = PCCAM_320_240;  
            RTNA_DBG_Str(0, " ** Still Resolution is 320x240\r\n"); 
            break;
        case 3:
            //160x120
            glPccamResolution = PCCAM_160_120;
            RTNA_DBG_Str(0, " ** Still Resolution is 160x120\r\n"); 
            break;
        }                               
        break;
#endif

#if ENABLE_MJPEG
    case MJPEG_FORMAT_INDEX:
        //m_VideoFmt = MMPS_3GPRECD_VIDEO_FORMAT_MJPEG;
        //pCamVidFmt = PCAM_USB_VIDEO_FORMAT_MJPEG ;
        //              USB_SetVideoFormat(PCAM_NONBLOCKING,PCAM_USB_VIDEO_FORMAT_MJPEG );
        USB_SetVideoFormat(PCAM_API, PCAM_USB_VIDEO_FORMAT_MJPEG);
        RTNA_DBG_Str(0, " ** Still Format is JPEG\r\n"); 
        switch(FrameIndex){
#if BIND_SENSOR_AR0832E
        case 1:
            //2592x1944
            glPccamResolution = PCCAM_2592_1944;
            RTNA_DBG_Str(0, " ** Still Resolution is 2592x1944\r\n"); 
            break;
        case 2:
            //2048x1536
            glPccamResolution = PCCAM_2048_1536;
            RTNA_DBG_Str(0, " ** Still Resolution is 2048x1536\r\n"); 
            break;
        case 3:
            //1920x1080
            glPccamResolution = PCCAM_1920_1080;
            RTNA_DBG_Str(0, " ** Still Resolution is 1920x1080\r\n"); 
            break;
        case 4:
            //1280x960
            glPccamResolution = PCCAM_1280_960;
            RTNA_DBG_Str(0, " ** Still Resolution is 1280x960\r\n"); 
            break;
        case 5:
            //1280x720
            glPccamResolution = PCCAM_1280_720;
            RTNA_DBG_Str(0, " ** Still Resolution is 1280x720\r\n"); 
            break;                 				
        case 6:
            //640x480
            glPccamResolution = PCCAM_640_480;	
            RTNA_DBG_Str(0, " ** Still Resolution is 640x480\r\n"); 
            break;
#else
        case 1:
            //1280x720
            glPccamResolution = PCCAM_1280_720;
            RTNA_DBG_Str(0, " ** Still Resolution is 1280x720\r\n"); 
            break;                              
        case 2:
            //640x480
            glPccamResolution = PCCAM_640_480;  
            RTNA_DBG_Str(0, " ** Still Resolution is 640x480\r\n"); 
            break;
        case 3:
            //640x360
            glPccamResolution = PCCAM_640_360;
            RTNA_DBG_Str(0, " ** Still Resolution is 640x360\r\n"); 
            break;
        case 4:
            //320x240
            glPccamResolution = PCCAM_320_240;
            RTNA_DBG_Str(0, " ** Still Resolution is 320x240\r\n");
            break;
        case 5:
            //320x180
            glPccamResolution = PCCAM_320_180;
            RTNA_DBG_Str(0, " ** Still Resolution is 320x180\r\n"); 
            break;                              
        case 6:
            //160x120
            glPccamResolution = PCCAM_160_120;  
            RTNA_DBG_Str(0, " ** Still Resolution is 160x120\r\n"); 
            break;
        case 7:
            //160x90
            glPccamResolution = PCCAM_160_90;
            RTNA_DBG_Str(0, " ** Still Resolution is 160x90\r\n"); 
            break;
#if BIND_SENSOR_AR0330
        case 8:
            //1920x1080
            glPccamResolution = PCCAM_1920_1080;
            RTNA_DBG_Str(0, " ** Still Resolution is 1920x1080\r\n"); 
            break;
        case 9:
            //2304x1296
            glPccamResolution = PCCAM_2304_1296;
            RTNA_DBG_Str(0, " ** Still Resolution is 2304x1296\r\n"); 
            break;
#endif
#endif
        }   
        break;
#endif
    }
}
#endif  //#if (USING_STILL_METHOD_1 == 0)

void usb_uvc_start_preview(void)
{
    if(gbUVCStartPreviewFlagSet == FALSE){
        gbUVCStartPreviewFlagSet = TRUE;
        usb_uvc_set_h264_mode(vp.bFormatIndex, vp.bFrameIndex);
        gbStillCaptureEvent = STILL_IMAGE_WAITING;

        MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_START_PREVIEW, 0, (void *) NULL);
    }/*else{
        USBEndpoint = 0;
        USBInPhase = SET_INTERFACE_CMD;
        usb_ep0_null_in();
    }*/
}

extern MMP_UBYTE gbsensortick_enable;
#if DRAM_SIZE <= 2
extern volatile MMP_BOOL gbIBCWritting;
#endif
void usb_uvc_stop_preview(void)
{
    AITPS_GBL   pGBL = AITC_BASE_GBL;
    AITPS_JPG   pJPG = AITC_BASE_JPG;
    AITPS_AIC   pAIC = AITC_BASE_AIC;
    AITPS_IBC   pIBC = AITC_BASE_IBC;
    PCAM_USB_VIDEO_FORMAT vidFmt;
    MMP_UBYTE prio_err,old_prio,new_prio;
    extern MMP_ULONG Cap_jpeg;

    if(gbUVCStartPreviewFlagSet == FALSE){
        gbUVCStopPreviewFlagSet = FALSE;

#if XU_FRAMEBASE_CAPTURE
        if(gFramebaseCap.JPEG){
            gFramebaseCap.JPEG = FALSE;
            RTNA_DBG_Str(3, "Close JPEG capture mode\r\n");
        }
        if(gFramebaseCap.SECS){
            gFramebaseCap.SECS = FALSE;
            gbCurH264Type = INVALID_H264;
            gFramebaseCap.format = CF_H264;
            RTNA_DBG_Str(3, "Close SECS mode\r\n");
        }
        Cap_jpeg = 0;
        gsCurH264Config.dwFrameInterval = 333333;
        gsCurH264Config.dwBitRate = 3000000;
#endif
#if 1   
        RTNA_DBG_Str(3, "SYS_FLAG_USB_STOP_PREVIEW\r\n");

        //According to Tomy. This are used for audio algorithm task. This would keep that task running while stopping the video.
        prio_err = MMPF_OS_ChangePrio(20, &old_prio, &new_prio);

        //#if USB_UVC_SKYPE
        gbSkypeMode = 0x01;
        gbCurH264Type = INVALID_H264;
        //#endif
        gbUvcCommitted = 0;
        vidFmt = pcam_get_info()->pCamVideoFormat;
        UsbDmaStop(PCCAM_TX1_EP_ADDR);

        if(vidFmt == PCAM_USB_VIDEO_FORMAT_H264){
            //MMPF_VIDENC_Stop();
            //RTNA_DBG_Str(3, "Stop H264 PCCAM\r\n");
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422){
            RTNA_DBG_Str(3, "Stop YUV422 PCCAM\r\n");
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV420){
            //RTNA_DBG_Str(3, "Stop YUV420 PCCAM\r\n");
        }
        // sean@2011_01_20
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_MJPEG){
#if (ENABLE_JPEG_ISR)
            //while(pJPG->JPG_CTL & JPG_ENC_EN);
            RTNA_AIC_IRQ_Dis(pAIC, AIC_SRC_JPG);
            // Blink 6.4 test
            if((pGBL->GBL_CLK_DIS0 & GBL_CLK_JPG_DIS) == 0x0){
                pJPG->JPG_INT_CPU_SR = JPG_INT_ENC_DONE;
            }
#endif
            RTNA_DBG_Str(3, "Stop MJPEG PCCAM\r\n");
        }
        else{
            dbg_printf(3, "Unknown format %d\r\n", vidFmt);
        }

        SetH264Mode(INVALID_H264);//disable H264 mode
#endif


#if 1
        ISP_IF_3A_Control(ISP_3A_DISABLE);

#if (SUPPORT_MP4) || (SUPPORT_MTS)
        if(MMPF_VIDMGR_GetMtsMuxModeEnable() || MMPF_VIDMGR_GetMP4Enable()){
            PCAM_USB_SetAudioWorkMode(MMPF_AUDIO_WORK_MODE_TS_MP4, MMPF_AUDIO_WORK_STATUS_SEND);                                
            USB_AudioPreviewStop(PCAM_API);
            MMPF_VIDMGR_SetMtsMuxModeEnable(MMP_FALSE);
            MMPF_VIDMGR_SetMP4Enable(MMP_FALSE);
        }
#endif

        vidFmt = pcam_get_info()->pCamVideoFormat;
        if(vidFmt == MMPS_3GPRECD_VIDEO_FORMAT_MJPEG){
            RTNA_DBG_Str(3, "<Fmt : Stop.MJPEG>\r\n");
            //MMPF_Sensor_CheckFrameStart(1);  // wait 2 frame for JPEG encode end

            gbStopMJPEGEvent = 1;
            gbdrawflag = 0;
        }
        else if((vidFmt == MMPS_3GPRECD_VIDEO_FORMAT_YUV422) || (vidFmt == MMPS_3GPRECD_VIDEO_FORMAT_YUV420)){
            const STREAM_CFG *cur_pipe = usb_get_stream_cfg();

            RTNA_DBG_Str(3, "<Fmt : Stop.YUV>\r\n");
            if(cur_pipe->pipe_en & PIPE0_EN){
                //#if DRAM_SIZE <= 2
#if 1
                if(IS_PIPE_RING(cur_pipe, 0)){
                    MMP_ULONG time_out = 100;
                    //                    pIBC->IBC_P0_INT_CPU_EN &= ~(IBC_INT_FRM_RDY);
                    pIBC->IBC_P0_INT_CPU_SR = IBC_INT_FRM_END;
                    while(!(pIBC->IBC_P0_INT_CPU_SR & IBC_INT_FRM_END));
                    pIBC->IBCP_0.IBC_BUF_CFG &= ~(IBC_STORE_EN);
                    goto test;
                    if(0){
                    }
                    else{
                        while(gbIBCWritting && (time_out > 0)){
                            time_out --;
                            MMPF_OS_Sleep(1);
                        }
                        DBG_S(1, "IBC Stop\r\n");
                    }
                    if(time_out == 0){
                        DBG_S(1, "IBC_Stop Timeout\r\n");
                        dbg_printf(3, "%X %X\r\n", pIBC->IBC_P0_INT_CPU_EN, pIBC->IBCP_0.IBC_BUF_CFG);
                    }
                    //usb_preclose_Tx_flag = 0;//FIXED this should not be needed. Fix this condition check later.
                    //usb_close_Tx_flag = 1;//FIXED this should not be needed. Fix this condition check later.
                    pIBC->IBC_P0_INT_CPU_EN &= ~(IBC_INT_FRM_RDY);
                    pIBC->IBCP_0.IBC_BUF_CFG &= ~(IBC_STORE_EN);
                }
                else
                #endif
                {
                    //test:
                    pIBC->IBC_P0_INT_CPU_EN &= ~(IBC_INT_FRM_RDY);
                    while(!(pIBC->IBC_P0_INT_CPU_SR & IBC_INT_FRM_RDY));
                    pIBC->IBCP_0.IBC_BUF_CFG &= ~(IBC_STORE_EN);
                }
            }
            if(cur_pipe->pipe_en & PIPE1_EN){
                pIBC->IBC_P1_INT_CPU_EN &= ~(IBC_INT_FRM_RDY);
                while(!(pIBC->IBC_P1_INT_CPU_SR & IBC_INT_FRM_RDY));
                pIBC->IBCP_1.IBC_BUF_CFG &= ~(IBC_STORE_EN);
            }
            if(cur_pipe->pipe_en & PIPE2_EN){
                pIBC->IBC_P2_INT_CPU_EN &= ~(IBC_INT_FRM_RDY);
                while(!(pIBC->IBC_P2_INT_CPU_SR & IBC_INT_FRM_RDY));
                pIBC->IBCP_2.IBC_BUF_CFG &= ~(IBC_STORE_EN);
            }
            //MMPF_Sensor_CheckFrameStart(1);  // wait 2 frame for H264 encode end
            test:
            gbStopYUV422Event = 1;
            gbdrawflag = 0;
        }
#if CAPTURE_BAYER_RAW_ENABLE
        else if(vidFmt == MMPS_3GPRECD_VIDEO_FORMAT_RAW){
            MMP_BOOL tmp = MMP_FALSE;
            RTNA_DBG_Str(3, "<Fmt : Stop.Raw>\r\n");
            MMPF_Sensor_SetParam(0, &tmp);
            MMPF_RAWPROC_EnableRawPath(MMP_FALSE);
            MMPF_VIF_EnableInputInterface(MMP_FALSE);                       
            gbdrawflag = 0;
        }
#endif
        else{
            RTNA_DBG_Str(3, "<Fmt : Stop.H264>\r\n");
            //MMPF_Sensor_CheckFrameStart(2);  // wait 2 frame for H264 encode end

            USB_VideoPreviewStop(PCAM_API);
            gbdrawflag = 0;
        }

        prio_err = MMPF_OS_ChangePrio(0, &new_prio, &old_prio);

#endif

        //       MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_USB_STOP_PREVIEW, MMPF_OS_FLAG_SET);   
        MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_STOP_PREVIEW, 0, (void *) NULL);
    }
    else{
        gbUVCStopPreviewFlagSet = TRUE;
        USBEndpoint = 0;
        USBInPhase = SET_INTERFACE_CMD;
        usb_ep0_null_in();
    }
    MMPF_OS_CheckStack();
}


#if USB_SUSPEND_TEST
void usb_uvc_suspend(void)
{
    gbUvcCommitted = 0;
    UsbDmaStop(PCCAM_TX1_EP_ADDR); // comment out for blink test
    // sean@2010_08_09 , add video power down in case !
    //USB_VideoPowerDown(PCAM_API) ;
#if SUPPORT_UAC
    PCAM_USB_SetAudioWorkMode(MMPF_AUDIO_WORK_MODE_UAC, MMPF_AUDIO_WORK_STATUS_SEND); 
    PCAM_USB_SetAudioWorkMode(MMPF_AUDIO_WORK_MODE_TS_MP4, MMPF_AUDIO_WORK_STATUS_SEND);    
    USB_AudioPreviewStop(PCAM_API/*PCAM_NONBLOCKING*/); // 2010_08_02 change to API call
#endif
}
#endif

MMPF_FCTL_LINK * usb_uvc_get_preview_fctl_link(MMP_UBYTE ubPipe)
{
    return &(gUvcPreviewFctlCfg[ubPipe]);
}

//extern PCAM_USB_VIDEO_FORMAT gsVidFmt ;
extern MMP_USHORT gsPreviewPath ;// sean@2011_06_08 // |= (1 << usIBCPipe);
MMP_BOOL usb_uvc_config_stream(void)
{
    MMP_BOOL mjpeg_stream = 0 ;
    STREAM_CFG const * stream_cfg = 0;
    MMP_UBYTE pipe0_cfg; 
    MMP_UBYTE pipe1_cfg;
    MMP_UBYTE pipe2_cfg;
    PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;

    if(vidFmt != PCAM_USB_VIDEO_FORMAT_H264){
        gbCurH264Type = INVALID_H264 ;
    }

    if(vidFmt == PCAM_USB_VIDEO_FORMAT_MJPEG){
        mjpeg_stream = 1 ;
        stream_cfg = &gsMJPEGStream_Cfg ;    
        gsVidRes = glPccamResolution;
        RTNA_DBG_Str3("Stream_Cfg is MJPEG\r\n");
    }
    else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422){
        RES_TYPE_CFG *cur_res;
        cur_res = GetResCfg(gsVidRes);

        mjpeg_stream = 0;
        if(cur_res->res_w * cur_res->res_h <= 640 * 480){
            stream_cfg = &gsYUY2Stream_Cfg ;
        }
        else{
            stream_cfg = &gsYUY2RingStream_Cfg;
            DBG_S(3, "ring");
        }
        DBG_S(3, "Stream_Cfg is YUY2\r\n");
    }
    else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV420){
        mjpeg_stream = 0;
        stream_cfg = &gsNV12Stream_Cfg ;
    }
#if CAPTURE_BAYER_RAW_ENABLE
    else if(vidFmt == PCAM_USB_VIDEO_FORMAT_RAW){
        mjpeg_stream = 0;
        stream_cfg = &gsRawStream_Cfg ;
    }
#endif
    else{
        extern RES_TYPE_LIST FB_s2_res;
        // H264 mode
        switch(gbCurH264Type){
#if USB_FRAMEBASE_H264_ONLY
        case FRAMEBASE_H264:
            RTNA_DBG_Str3("[!]Frame Base H264 is defined\r\n");
            mjpeg_stream = 0;
            stream_cfg = &gsH264PureStream_Cfg ;
            break;
#endif
#if USB_FRAMEBASE_H264_YUY2_STREAM
        case FRAMEBASE_H264_YUY2:
            RTNA_DBG_Str3("[!]Frame Base H264 + YUY2 is defined\r\n");
            mjpeg_stream = 0;
            stream_cfg = &gsH264FrameYUY2Stream_Cfg ;
            break;
#endif
#if USB_FRAMEBASE_DUAL_H264_STREAM
        case FRAMEBASE_DUAL_H264:
            RTNA_DBG_Str3("[!]Frame Base Dual H264 is defined\r\n");
            mjpeg_stream = 0;
            gsVidRes = FB_s2_res;
            stream_cfg = &gsH264FrameDualStream_Cfg ;
            break;
        case FRAMEBASE_DUAL_H264_MJPEG:
            RTNA_DBG_Str3("[!]Frame Base Dual H264 + MJPEG is defined\r\n");
            mjpeg_stream = 1;
            gsVidRes = FB_s2_res;
            stream_cfg = &gsH264FrameDual_MJPGStream_Cfg ;
            break;
#endif
#if USB_FRAMEBASE_H264_MJPEG_STREAM
        case FRAMEBASE_H264RT_MJPEG:
            RTNA_DBG_Str3("[!]Frame Base RT H264 + MJPEG is defined\r\n");
            mjpeg_stream = 1;
            pcam_get_info()->pCamVideoRes = glPccamResolution;
            gsVidRes = FB_s2_res;//MJPEG in pipe 0
            stream_cfg = &gsH264RTMJPEGStream_Cfg ;
            break;
        case FRAMEBASE_H264FRAME_MJPEG:
            RTNA_DBG_Str3("[!]Frame Base Frame H264 + MJPEG is defined\r\n");
            mjpeg_stream = 1;
            gsVidRes = FB_s2_res;//MJPEG in pipe 2
            stream_cfg = &gsH264FrameMJPGStream_Cfg ;
            break;
#endif
            //#if USB_UVC_SKYPE && 0/*not maintained anymore*/
#if SKYPE_MODE_B
        case SKYPE_H264:
            if(gbSkypeMode == 0x02){
                RTNA_DBG_Str3("[!]Skype H264 is defined\r\n");
                mjpeg_stream = 0;
                stream_cfg = &gsSkyModeBStream_Cfg ;
            }                
            break;
#endif
#if USB_MJPEGH264_STREAM
        case UVC_H264:
            RTNA_DBG_Str3("[!]UVC H264 is defined\r\n");
            if(gsH264EncoderVFC_Cfg_Cur.bStreamMuxOption & DUAL_STREAM_EN){
                if(gsH264EncoderVFC_Cfg_Cur.bStreamMuxOption & DUAL_MJPEG_H264){
                    mjpeg_stream = 1 ;
                    stream_cfg = &gsH264MJPEGStream_Cfg ;
                }
            }
            break ;
#endif
#if (SECS_VER > 0)
        case SKYPE_TX_STREAM:
#if XU_FRAMEBASE_CAPTURE
            if(gFramebaseCap.SECS == MMP_TRUE){
                gsSkypeStreamFormat_Commit_Cur[0].bStreamType = SKYPE_FORMAT_H264;
            }
            dbg_printf(3, "Capture_SECS : %d\r\n", gFramebaseCap.SECS);
#endif
            if(gsSkypeStreamFormat_Commit_Cur[0].bStreamType == SKYPE_FORMAT_H264){
                RTNA_DBG_Str3("[!]Skype Transport Stream is defined\r\n");
                mjpeg_stream = 0;
                stream_cfg = &gsSkyTransportStream_Cfg ;
            }                
            break;
#endif
#if SKYPE_UVC_H264
        case UVC_H264_STREAM:
            if(gsCurH264Config.bStreamMuxOption & DUAL_AUX_H264){
                RTNA_DBG_Str3("[!]Skype UVC H.264 Stream is defined\r\n");
                mjpeg_stream = 0;
                stream_cfg = &gsSkypeUVCH264Stream_Cfg ;
            }                
            break;
#endif
        }
    }        
    if(stream_cfg == 0){
        dbg_printf(2, "[ERR] unknown stream vidFmt=%d, gbCurH264Type=%d\r\n", vidFmt, gbCurH264Type);
    }
    
    usb_set_stream_cfg(stream_cfg);

    // sean@2011_04_13, config width & height into stream cfg here.
    //pipe0_cfg =  stream_cfg->pipe_cfg & PIPE_CFG_MASK ;
    //pipe1_cfg = (stream_cfg->pipe_cfg>>4) & PIPE_CFG_MASK ;
    pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);
    pipe2_cfg = GET_PIPE_FORMAT(stream_cfg, 2);

    // Single stream @ pipe 0

    if(stream_cfg->pipe_en == PIPE0_EN){
        usb_uvc_config_pipe(stream_cfg, gsVidRes, PCCAM_RES_NUM, PCCAM_RES_NUM);
        gsPreviewPath |= (1 << 0) ;
    }
    // Single stream @ pipe 1
    else if(stream_cfg->pipe_en == PIPE1_EN){
        if(pipe1_cfg == PIPE_CFG_H264){
            PCAM_USB_INFO *pcamInfo = pcam_get_info(); 
            usb_uvc_config_pipe(stream_cfg, PCCAM_RES_NUM, pcamInfo->pCamVideoRes, PCCAM_RES_NUM);    
        }
        else{
            usb_uvc_config_pipe(stream_cfg, PCCAM_RES_NUM, gsVidRes, PCCAM_RES_NUM);
            gsPreviewPath |= (1 << 1) ;
        }
    }
    // Single stream @ pipe 2
    else if(stream_cfg->pipe_en == PIPE2_EN){
        usb_uvc_config_pipe(stream_cfg, PCCAM_RES_NUM, PCCAM_RES_NUM, gsVidRes);
        gsPreviewPath |= (1 << 2) ;
    }
    else if((stream_cfg->pipe_en & PIPE_EN_MASK) == (PIPE0_EN | PIPE1_EN)){
        PCAM_USB_INFO *pcamInfo = pcam_get_info(); 
        if((pipe0_cfg == PIPE_CFG_MJPEG) && (pipe1_cfg == PIPE_CFG_H264)){  // pipe0 is mjpeg, pipe1 is h264
            usb_uvc_config_pipe(stream_cfg, gsVidRes, pcamInfo->pCamVideoRes, PCCAM_RES_NUM);
        }
        else if(pipe1_cfg == PIPE_CFG_H264){
            usb_uvc_config_pipe(stream_cfg, pcamInfo->pCamVideoRes, gsVidRes, PCCAM_RES_NUM);
        } 
        else if (pipe1_cfg==PIPE_CFG_MJPEG) {
            // pipe 1 is jpeg use main resolution variable
            // pipe 0 is yuy2 , now is same res with mjpeg
            usb_uvc_config_pipe(stream_cfg, gsVidRes, gsVidRes, PCCAM_RES_NUM);
        }
    }
    else if((stream_cfg->pipe_en & PIPE_EN_MASK) == (PIPE0_EN | PIPE1_EN | PIPE2_EN)){
        if((pipe1_cfg == PIPE_CFG_H264) && (pipe2_cfg == PIPE_CFG_MJPEG)){
            PCAM_USB_INFO *pcamInfo = pcam_get_info();
#if (CUSTOMER == ANW)
        #if SUPPORT_H264MV_MD
            if(pcamInfo->pCamVideoRes == PCCAM_1280_720){
                gsVidRes = PCCAM_640_360;
            }
            else{
                gsVidRes = PCCAM_640_480;
            }
        #endif
        #if SUPPORT_AIT845x_MD
            if((pcamInfo->pCamVideoRes == PCCAM_1280_720)||
               (pcamInfo->pCamVideoRes == PCCAM_640_360)||
               (pcamInfo->pCamVideoRes == PCCAM_320_180)||
               (pcamInfo->pCamVideoRes == PCCAM_160_90)){
                gsVidRes = PCCAM_320_180;
            }
            else{
                gsVidRes = PCCAM_320_240;
            }
        #endif
            usb_uvc_config_pipe(stream_cfg, pcamInfo->pCamVideoRes, gsVidRes, pcamInfo->pCamVideoRes);
#else
            usb_uvc_config_pipe(stream_cfg, pcamInfo->pCamVideoRes, gsVidRes, gsVidRes);
#endif            
        }
    }
#if SUPPORT_OSD_FUNC
    {
        extern MMP_ULONG OSD_CurrentW[],OSD_CurrentH[];
        extern MMP_ULONG OSD_FontW[],OSD_FontH[];
        if(stream_cfg->pipe_en & PIPE0_EN) {
            OSD_CurrentW[0] = PIPE_INFO(0, w);
            OSD_CurrentH[0] = PIPE_INFO(0, h);

#if (CUSTOMER == ANW)
            if(OSD_CurrentW[0] == 1280){
                OSD_FontW[0] = 12;
                OSD_FontH[0] = 14;
            }
            else if(OSD_CurrentW[0] == 640){
                OSD_FontW[0] = 8;
                OSD_FontH[0] = 10;
            }
            else{
                OSD_FontW[0] = 6;
                OSD_FontH[0] = 8;
            }
#else

            OSD_FontW[0] = 16;
            OSD_FontH[0] = 16;

#endif
        }
        if(stream_cfg->pipe_en & PIPE1_EN) {
            OSD_CurrentW[1] = PIPE_INFO(1, w);
            OSD_CurrentH[1] = PIPE_INFO(1, h);
#if (CUSTOMER == ANW)
            if(OSD_CurrentW[1] == 1280){
                OSD_FontW[1] = 12;
                OSD_FontH[1] = 14;
            }
            else if(OSD_CurrentW[1] == 640){
                OSD_FontW[1] = 8;
                OSD_FontH[1] = 10;
            }
            else{
                OSD_FontW[1] = 6;
                OSD_FontH[1] = 8;
            }
#else

            OSD_FontW[1] = 16;
            OSD_FontH[1] = 16;

#endif
        }
        if(stream_cfg->pipe_en & PIPE2_EN) {
            OSD_CurrentW[2] = PIPE_INFO(2,w);
            OSD_CurrentH[2] = PIPE_INFO(2,h);
        }
    }
#endif

    return mjpeg_stream ;
}

/*
 * @brief Config the resolutions of STREAM_CFG structure.
 * */
void usb_uvc_config_pipe(const STREAM_CFG *stream_cfg, PCAM_USB_VIDEO_RES pipe0_res, PCAM_USB_VIDEO_RES pipe1_res, PCAM_USB_VIDEO_RES pipe2_res)
{
    RES_TYPE_CFG *cur_res;

    PIPE_INFO(0, bDirty) = MMP_FALSE;
    PIPE_INFO(1, bDirty) = MMP_FALSE;
    PIPE_INFO(2, bDirty) = MMP_FALSE;
    PIPE_INFO(0, w) = 0;
    PIPE_INFO(0, h) = 0;
    PIPE_INFO(1, w) = 0;
    PIPE_INFO(1, h) = 0;
    PIPE_INFO(2, w) = 0;
    PIPE_INFO(2, h) = 0;

    if(stream_cfg->pipe_en & PIPE0_EN){
        cur_res = GetResCfg(pipe0_res);
        PIPE_INFO(0, w) = cur_res->res_w;
        PIPE_INFO(0, h) = cur_res->res_h;
    }
    if(stream_cfg->pipe_en & PIPE1_EN){
        cur_res = GetResCfg(pipe1_res);
        PIPE_INFO(1, w) = cur_res->res_w;
        PIPE_INFO(1, h) = cur_res->res_h;
    }
    if(stream_cfg->pipe_en & PIPE2_EN){
        cur_res = GetResCfg(pipe2_res);
        PIPE_INFO(2, w) = cur_res->res_w;
        PIPE_INFO(2, h) = cur_res->res_h;
    }
#if 1
dbg_printf(3,"stream_cfg->pipe_en :x%x\r\n",stream_cfg->pipe_en);
dbg_printf(3,"stream_cfg->pipe_cfg:x%x\r\n",stream_cfg->pipe_cfg);
dbg_printf(3,"stream_cfg->pipe0_w :%d\r\n",PIPE_INFO(0,w));
dbg_printf(3,"stream_cfg->pipe0_h :%d\r\n",PIPE_INFO(0,h));
dbg_printf(3,"stream_cfg->pipe1_w :%d\r\n",PIPE_INFO(1,w));
dbg_printf(3,"stream_cfg->pipe1_h :%d\r\n",PIPE_INFO(1,h));
dbg_printf(3,"stream_cfg->pipe2_w :%d\r\n",PIPE_INFO(2,w));
dbg_printf(3,"stream_cfg->pipe2_h :%d\r\n",PIPE_INFO(2,h));
#endif
}

void usb_uvc_init_stream(MMP_BOOL mjpeg_stream)
{
    const STREAM_CFG *stream_cfg ;
    PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;
    stream_cfg = usb_get_stream_cfg();

    MMPF_Timer_InitLog(&tlH264, MMPF_TIMER_OS, "H264");
    MMPF_Timer_InitLog(&tlRd0, MMPF_TIMER_OS, "Pipe0 Read Start");
    MMPF_Timer_InitLog(&tlRd0E, MMPF_TIMER_OS, "Pipe0 Read End");
    MMPF_Timer_InitLog(&tlWr0, MMPF_TIMER_OS, "Pipe0 Write End");
    MMPF_Timer_InitLog(&tlWr0S, MMPF_TIMER_OS, "Pipe0 Write Start");
    MMPF_Timer_InitLog(&tlPkt0, MMPF_TIMER_OS, "First UVC PKT");
    if(stream_cfg){
        //stream_cfg->pipe_sync = 0;
        usb_uvc_start_stream(mjpeg_stream, stream_cfg, glPccamResolution); 

#if 0
        {
            //PCAM_USB_ZOOM val ;
            PCAM_USB_ZOOM  *zoomInfo = (PCAM_USB_ZOOM *) (&pcam_get_info()->pCamDigZoom);
            PCAM_USB_PANTILT  *panInfo = (PCAM_USB_PANTILT *) (&pcam_get_info()->pCamDigPan);

            //zoomInfo = (PCAM_USB_ZOOM *)(&pcam_get_info()->pCamDigZoom) ;

            zoomInfo->Dir = 0 ;
            zoomInfo->RangeMin = 0 ;
            zoomInfo->RangeMax = gsZoom ;
            zoomInfo->RangeStep = ZOM_MAX;
            SetVideoZoomByJump(zoomInfo, 0);

            panInfo->PanMin = 0;
            panInfo->PanMax = glPan;
            panInfo->TiltMin = 0;
            panInfo->TiltMax = glTilt;
            panInfo->Steps = (PAN_MAX - PAN_MIN) / PANTILT_RES;
            SetVideoPanTiltByJump(panInfo, 0);
        }
#endif

        if(vidFmt == PCAM_USB_VIDEO_FORMAT_H264){
            //RTNA_DBG_Str(0, "MMPS_3GPRECD_StartRecord begin...\r\n");
            MMPS_3GPRECD_StartRecord();                
            //RTNA_DBG_Str(0, "MMPS_3GPRECD_StartRecord end...\r\n");
        }
    }
    UvcSampleBuilder.nFrame = 0;
}        

void usb_uvc_start_stream(MMP_BOOL mjpeg_stream, const STREAM_CFG *stream_cfg, MMP_ULONG res)
{
    AITPS_JPG   pJPG = AITC_BASE_JPG;
    AITPS_AIC   pAIC = AITC_BASE_AIC;
    MMP_USHORT  max_frame_rate = 0 ;
    RES_TYPE_CFG *cur_res;
    MMP_UBYTE   pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    MMP_UBYTE   pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);
    MMP_UBYTE   pipe2_cfg = GET_PIPE_FORMAT(stream_cfg, 2);
    MMP_LONG    wr_ptr;
    MMPF_ICO_PIPEATTRIBUTE  IconAttr;
    MMPF_IBC_PIPEATTRIBUTE  IbcAttr;
    MMPF_FCTL_LINK          *pPreviewFctl;
    extern RES_TYPE_LIST FB_s2_res;

    gPCCamCurRes = cur_res = GetResCfg(res);
    if(cur_res == NULL){
        RTNA_DBG_Str3("Wrong resolution setting ....\r\n");
        return;
    }

    if(!mjpeg_stream){
        // YUY2 + H264
        RTNA_DBG_Str(0, "InitScale() begin...\r\n");
        InitScale(stream_cfg, res);
        RTNA_DBG_Str(0, "InitScale() end...\r\n");
    }
    else{
        // MJPEG+ H264    
#if USB_FRAMEBASE_H264_ONLY
        if(gbCurH264Type == FRAMEBASE_H264){
            // This is test code to test dual stream MJPEG + H264
            // JPEG is running, but no JPEG streaming case
            RTNA_DBG_Str(0, "MMPF_InitPCCam() begin...1\r\n");    
            InitScale(stream_cfg, res);
        }
#else
        if(0){
        }
#endif
#if USB_FRAMEBASE_H264_MJPEG_STREAM
        else if((FRAMEBASE_H264RT_MJPEG == gbCurH264Type) || (FRAMEBASE_H264FRAME_MJPEG == gbCurH264Type)){
            MMPF_InitPCCam(stream_cfg, FB_s2_res);
        }
#endif
#if USB_FRAMEBASE_DUAL_H264_STREAM
        else if((FRAMEBASE_DUAL_H264 == gbCurH264Type) || (FRAMEBASE_DUAL_H264_MJPEG == gbCurH264Type)){
            MMPF_InitPCCam(stream_cfg, FB_s2_res);
        }
#endif
#if SUPPORT_S_FRAMEBASE
        else if(gbCurH264Type == FRAMEBASE_MJPEG_Y || gbCurH264Type == FRAMEBASE_MJPEG_YUY2){
            RTNA_DBG_Str(0, "MMPF_InitPCCam() begin...2\r\n");    
            MMPF_InitPCCam(stream_cfg, PCCAM_640_480);
        }
#endif
        else{
            RTNA_DBG_Str(0, "MMPF_InitPCCam() begin...3\r\n");    
            MMPF_InitPCCam(stream_cfg, res);
        }
        RTNA_DBG_Str(0, "MMPF_InitPCCam() end...\r\n");
    }   
    // sean@2010_11_01 , set the max frame rate
    max_frame_rate = GetMaxFrameRate(res) ;

    if(gbStillCaptureEvent == STILL_IMAGE_WAITING){
        //init IQ param
        usb_vc_init_sensor_param();
#if XU_FRAMEBASE_CAPTURE
        if(gbCurH264Type == INVALID_H264)
            ISP_IF_AE_SetFPS(gFramebaseCap.orgFramerate);
#endif
        ISP_IF_AE_SetFastMode(1); //do fastmode about 4 times AE calc.
        RTNA_DBG_Str3("Enable AE Fast Mode\r\n");
        //ISP_IF_AE_SetFPS(max_frame_rate); //patrick test
        //ISP_IF_AE_SetFPS(0);
    }

#if SUPPORT_AUTO_FOCUS
    if(gbStillCaptureEvent == STILL_IMAGE_WAITING){
        MMPF_Sensor_AutoFocus();
        RTNA_DBG_Str(0, "MMPF_Sensor_AutoFocus()\r\n");
    }
#endif

    gbStopYUV422Event = 0;
    glPCCamCnt = 0;

    IbcAttr.ulLineCnt = 0xFFFFFFFF;
    if(stream_cfg->pipe_en & PIPE0_EN){
        if(pipe0_cfg != PIPE_CFG_H264){
            pPreviewFctl = usb_uvc_get_preview_fctl_link(0);

            //turn off pre frame ready INT
            MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_PRERDY, MMP_FALSE);

            IconAttr.inputsel = pPreviewFctl->scalerpath;
            IconAttr.bDlineEn = MMP_TRUE;
            MMPF_ICON_SetAttributes(pPreviewFctl->icopipeID, &IconAttr);

            wr_ptr = (MMP_ULONG) MMPF_Video_CurWrPtr(PIPE_0);
            switch(pipe0_cfg){
            case PIPE_CFG_NV12:
                IbcAttr.function = MMPF_IBC_FX_TOFB;
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                IbcAttr.ulBaseUAddr = IbcAttr.ulBaseAddr + cur_res->res_w * cur_res->res_h;
                IbcAttr.ulBaseVAddr = IbcAttr.ulBaseUAddr + ((cur_res->res_w * cur_res->res_h) >> 2);
                IbcAttr.colorformat = MMPF_IBC_COLOR_NV12;
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                break;
            case PIPE_CFG_YUY2:
                //case PIPE_CFG_Y:
#if DRAM_SIZE <= 2
                if(IS_PIPE_RING(stream_cfg, 0)){
                    IbcAttr.function = MMPF_IBC_FX_RING_BUF;

                    if(gbCurH264Type == SKYPE_TX_STREAM)
                        IbcAttr.ulBaseEndAddr = wr_ptr + MMPF_Video_GetStreamCtlInfo(PIPE_0)->slot_size - 64;
                    else
                        IbcAttr.ulBaseEndAddr = wr_ptr + MMPF_Video_GetStreamCtlInfo(PIPE_0)->slot_size;
                    IbcAttr.ulLineCnt = 1;
                    MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_PRERDY, MMP_TRUE);
                    MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_ST, MMP_TRUE);
                }
                else{
                    IbcAttr.function = MMPF_IBC_FX_TOFB;
                    MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_ST, MMP_FALSE);
                }
#else
                IbcAttr.function = MMPF_IBC_FX_TOFB;
#endif
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                {
#if 1//def ZDW_BARCODE
                  IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                    IbcAttr.colorformat = MMPF_IBC_COLOR_YUV420_LUMI_ONLY;
#else
                    //IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                    IbcAttr.ulBaseUAddr = IbcAttr.ulBaseAddr + cur_res->res_w * cur_res->res_h;
                    IbcAttr.ulBaseVAddr = IbcAttr.ulBaseUAddr + ((cur_res->res_w * cur_res->res_h) >> 1);
                    IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422_YUYV;
#endif
                }
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                RTNA_DBG_Str(0, "YUY2 PIPE0 enable\r\n");
                break;
            case PIPE_CFG_MJPEG:
                IbcAttr.function = MMPF_IBC_FX_JPG;
                IbcAttr.ulBaseAddr = IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422;
                RTNA_DBG_Str(0,"MJPEG PIPE0 enable\r\n");
                break;
            default:
                DBG_S(0, "#Error : Unknown config for PIPE0\r\n");
                break;
            }

            IbcAttr.bMirrorEnable = MMP_FALSE;
            IbcAttr.usMirrorWidth = cur_res->res_w;
            IbcAttr.ulLineOffset = 0;
            IbcAttr.InputSource = pPreviewFctl->icopipeID;

            MMPF_IBC_SetAttributes(pPreviewFctl->ibcpipeID, &IbcAttr);
            MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_RDY, MMP_TRUE);
        }
    }
    if(stream_cfg->pipe_en & PIPE1_EN){
        if(pipe1_cfg != PIPE_CFG_H264){
            pPreviewFctl = usb_uvc_get_preview_fctl_link(1);

            IconAttr.inputsel = pPreviewFctl->scalerpath;
            IconAttr.bDlineEn = MMP_TRUE;
            MMPF_ICON_SetAttributes(pPreviewFctl->icopipeID, &IconAttr);

            wr_ptr = (MMP_ULONG) MMPF_Video_CurWrPtr(PIPE_1);
            switch(pipe1_cfg){
            case PIPE_CFG_NV12:
                IbcAttr.function = MMPF_IBC_FX_TOFB;
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                IbcAttr.ulBaseUAddr = IbcAttr.ulBaseAddr + cur_res->res_w * cur_res->res_h;
                IbcAttr.ulBaseVAddr = IbcAttr.ulBaseUAddr + ((cur_res->res_w * cur_res->res_h) >> 2);
                IbcAttr.colorformat = MMPF_IBC_COLOR_NV12;
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                break;
            case PIPE_CFG_YUY2:
                IbcAttr.function = MMPF_IBC_FX_TOFB;
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422_YUYV;
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                RTNA_DBG_Str(0, "YUY2 PIPE1 enable\r\n");  
                break;
            case PIPE_CFG_MJPEG:
                IbcAttr.function = MMPF_IBC_FX_JPG;
                IbcAttr.ulBaseAddr = IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422;
                break;
            default:
                DBG_S(0, "#Error : Unknown config for PIPE1\r\n");
                break;
            }
            IbcAttr.bMirrorEnable = MMP_FALSE;
            IbcAttr.usMirrorWidth = 0;
            IbcAttr.ulLineOffset = 0;
            IbcAttr.InputSource = pPreviewFctl->icopipeID;
            MMPF_IBC_SetAttributes(pPreviewFctl->ibcpipeID, &IbcAttr);
            MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_RDY, MMP_TRUE);
        }
    }
    if(stream_cfg->pipe_en & PIPE2_EN){
        if(pipe2_cfg != PIPE_CFG_H264){
            pPreviewFctl = usb_uvc_get_preview_fctl_link(2);

            IconAttr.inputsel = pPreviewFctl->scalerpath;
            IconAttr.bDlineEn = MMP_TRUE;
            MMPF_ICON_SetAttributes(pPreviewFctl->icopipeID, &IconAttr);

            wr_ptr = (MMP_ULONG) MMPF_Video_CurWrPtr(PIPE_2);
            switch(pipe2_cfg){
            case PIPE_CFG_NV12:
                IbcAttr.function = MMPF_IBC_FX_TOFB;
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                IbcAttr.ulBaseUAddr = IbcAttr.ulBaseAddr + cur_res->res_w * cur_res->res_h;
                IbcAttr.ulBaseVAddr = IbcAttr.ulBaseUAddr + ((cur_res->res_w * cur_res->res_h) >> 2);
                IbcAttr.colorformat = MMPF_IBC_COLOR_NV12;
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                break;
            case PIPE_CFG_YUY2:
                IbcAttr.function = MMPF_IBC_FX_TOFB;
                IbcAttr.ulBaseAddr = wr_ptr + FRAME_PAYLOAD_HEADER_SZ;
                IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422_YUYV;
                MMPF_IBC_SetStoreEnable(pPreviewFctl->ibcpipeID, MMP_TRUE);
                RTNA_DBG_Str(0, "YUY2 PIPE2 enable\r\n");  
                break;
            case PIPE_CFG_MJPEG:
                IbcAttr.function = MMPF_IBC_FX_JPG;
                IbcAttr.ulBaseAddr = IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
                IbcAttr.colorformat = MMPF_IBC_COLOR_YUV422;
                RTNA_DBG_Str(0, "MJPEG PIPE2 enable\r\n");  
                break;
            default:
                DBG_S(0, "#Error : Unknown config for PIPE2\r\n");
                break;
            }
            IbcAttr.bMirrorEnable = MMP_FALSE;
            IbcAttr.usMirrorWidth = 0;
            IbcAttr.ulLineOffset = 0;
            IbcAttr.InputSource = pPreviewFctl->icopipeID;
            MMPF_IBC_SetAttributes(pPreviewFctl->ibcpipeID, &IbcAttr);
            MMPF_IBC_SetInterruptEnable(pPreviewFctl->ibcpipeID, MMPF_IBC_EVENT_FRM_RDY, MMP_TRUE);
        }
    }

#if (MJPG_FPS_CTL == 1)
    MJPGFrameRateCtlInitial();
#endif

    if(mjpeg_stream){
        glPCCamJpegSize = 0;
        gbStopMJPEGEvent = 0;
#if (ENABLE_JPEG_ISR)
        RTNA_AIC_Open(pAIC, AIC_SRC_JPG, jpg_isr_a, AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
        RTNA_AIC_IRQ_En(pAIC, AIC_SRC_JPG);

        pJPG->JPG_INT_CPU_SR = JPG_INT_ENC_DONE;
        pJPG->JPG_INT_CPU_EN = JPG_INT_ENC_DONE;
#endif

        if((gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG)){
#if (SUPPORT_OSD_FUNC == 0)
            if(gbSkypeMode==0x86) {
            } else
#endif
            {
#if (CUSTOMER == ANW)
                gbGraphicLoopBackSource = PIPE_0;  // assign which pipe to be loopback source
#else
                gbGraphicLoopBackSource = PIPE_1;  // assign which pipe to be loopback source
#endif            
                glGraphicLoopBackCnt = 0;
                gbGraLBEvent = 1;  // trigger Graphic loopback event
            }
        }
        else{
            pJPG->JPG_CTL |= JPG_ENC_EN;
        }
    }

    MMPF_Sensor_3A_SetInterrupt(MMP_TRUE);

    if(pcam_get_info()->pCamVideoFormat == PCAM_USB_VIDEO_FORMAT_H264){
        //Note: FRAMEBASE_Y, FRAMEBASE_NV12, FRAMEBASE_MJPEG_Y, FRAMEBASE_MJPEG_YUY2
        //      also use this API to enable preview

        switch(gbCurH264Type){
#if SUPPORT_S_FRAMEBASE
        case FRAMEBASE_Y:
        case FRAMEBASE_NV12:
            MMPD_System_EnableClocks(PREVIEW_CLOCKS, MMP_TRUE);
            /*
            MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_GRA, MMP_TRUE);
            MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_DMA, MMP_TRUE);
            MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_IBC, MMP_TRUE);
            MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_TRUE);
            MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_ICON, MMP_TRUE);
            */
            m_bVidRecdPreviewStatus = MMP_TRUE;
            MMPF_VIF_EnableInputInterface(MMP_TRUE);
            break;
        case FRAMEBASE_MJPEG_Y:
        case FRAMEBASE_MJPEG_YUY2:
        case FRAMEBASE_H264_YUY2:
        case FRAMEBASE_H264_Y:
#endif
#if USB_FRAMEBASE_DUAL_H264_STREAM
        case FRAMEBASE_DUAL_H264:
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_0, MMP_TRUE, MMP_FALSE);
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_1, MMP_TRUE, MMP_FALSE);
            m_bVidRecdPreviewStatus = MMP_TRUE;
            break;
        case FRAMEBASE_DUAL_H264_MJPEG:
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_0, MMP_TRUE, MMP_FALSE);
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_1, MMP_TRUE, MMP_FALSE);
            m_bVidRecdPreviewStatus = MMP_TRUE;
            MMPF_VIF_EnableInputInterface(MMP_TRUE);
            break;
#endif
#if USB_FRAMEBASE_H264_MJPEG_STREAM
        case FRAMEBASE_H264FRAME_MJPEG:
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_0, MMP_TRUE, MMP_FALSE);
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_1, MMP_TRUE, MMP_FALSE);
            m_bVidRecdPreviewStatus = MMP_TRUE;
            MMPF_VIF_EnableInputInterface(MMP_TRUE);
            break;
#endif
        default:
            MMPF_Fctl_EnablePreview(MMPF_IBC_PIPE_1, MMP_TRUE, MMP_FALSE);
            m_bVidRecdPreviewStatus = MMP_TRUE;
            break;
        }
    }
    else{
        MMPD_System_EnableClocks(PREVIEW_CLOCKS, MMP_TRUE);
        /*
        MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_GRA, MMP_TRUE);
        MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_DMA, MMP_TRUE);
        MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_IBC, MMP_TRUE);
        MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_SCAL, MMP_TRUE);
        MMPD_System_EnableClock(MMPD_SYSTEM_CLK_MODULE_ICON, MMP_TRUE);
        */
        m_bVidRecdPreviewStatus = MMP_TRUE;
        MMPF_VIF_EnableInputInterface(MMP_TRUE);
    }

    RTNA_AIC_IRQ_En(pAIC, AIC_SRC_VIF);
    RTNA_AIC_IRQ_En(pAIC, AIC_SRC_ISP);
    RTNA_AIC_IRQ_En(pAIC, AIC_SRC_IBC);
    
    //MMPF_Sensor_CheckFrameStart(1);  // wait 1 frame for JPEG encode end
}

void usb_uvc_align_jpeg_height(MMP_UBYTE *jpeg, MMP_ULONG len, MMP_USHORT new_h)
{
    MMP_USHORT tagID = 0,tagLength = 0 ;
    MMP_UBYTE  *jpegBuf = jpeg ;

    if((new_h & 7) == 0){
        return ;
    }
    do{
        if(!MMPF_GetJfifTag(&tagID, &tagLength, &jpegBuf, len)){
            if(tagID == 0xFFC0){
                break;
            } 
            len = len - tagLength - 2 ;
            jpegBuf += (tagLength + 2);
        }
    }
    while(len > 0);
    jpegBuf[5] = (new_h >> 8);
    jpegBuf[6] = (new_h & 0xFF);
    //dbg_printf(3,"jpeg h : %d,new_h : %d\r\n",(jpegBuf[5] << 8) | jpegBuf[6],new_h );
}


MMP_UBYTE * usb_uvc_search_app3_insert_addr(MMP_UBYTE *jpeg, MMP_ULONG len, MMP_USHORT tag)
{
    MMP_USHORT tagID = 0,tagLength = 0 ;
    MMP_UBYTE  *jpegBuf = jpeg ;

    do{
        if(!MMPF_GetJfifTag(&tagID, &tagLength, &jpegBuf, len)){
            len = len - tagLength - 2 ;
            jpegBuf += (tagLength + 2);
        }
    }
    while(tagID != tag && len > 0); 
    return jpegBuf ;
}

//HW writing and USB sending at the same time
typedef enum _REAL_TIME_TX_PHASE {
    RT_TX_IDLE,    //waiting for other image
    RT_TX_ACTIVE,  //It's turn for YUV sending
    RT_TX_SENDING, //YUV is sending
    RT_TX_END      //end of YUV sending
} REAL_TIME_TX_PHASE;

//frame buffer control used for USB TX
typedef struct _TX_FRAME_BUF
{
    volatile MMP_BOOL bKeepSending;
    MMP_ULONG ProcSize; //the processed size of ring buffer. It might be moved size, if move_packet is used.
    // or it could be bytes been sent to USB DMA
    REAL_TIME_TX_PHASE phase; //used in YUV ring only.
}TX_FRAME_BUF;

/* This structure stores how STREAM_DMA_BLK make into USB transfers.
 * for ISO transfer, see Figure 2-13, UVC 1.1 SPEC. Typically up to 3048-12 bytes in HS.
 * for Bulk transfer, see Figure 2-10, UVC 1.1 SPEC. May up to 30K
 * each transfer includes one or more USB micro-frames. Typically up to 3 K in HS-ISO and more on bulk.
 * each transfer needs a 12-byte UVC payload header.
 */
typedef struct _USB_TRANSFER_INFO
{
    //STREAM_DMA_BLK fields
    MMP_ULONG  tx_len;    //bytes transfered in this STREAM_DMA_BLK
    MMP_ULONG  tx_cnt;    //number of UVC transfers sent in this STREAM_DMA_BLK.
    //This is not USB packets
    MMP_ULONG  cur_addr; //current data address in the current STREAM_DMA_BLK

    // UVC 12 byte payload header fields
    volatile MMP_ULONG PTS;
#if STREAM_DMA_BLK_VER == 2
    MMP_ULONG  dma_buf[2];//12 Bytes UVC payload header buffer +  image data = max 3K
#elif STREAM_DMA_BLK_VER == 3
    MMP_ULONG  ph_buf[2];//12 Bytes UVC payload header buffer only
    MMP_BOOL   bPhToggle;//indicate which ph_buf to be used.
#endif
    MMP_UBYTE  toggle;   //frame toggle used in 12-byte UVC payload header

    // source control
    MMP_BOOL   bSrcPause;//if the source is paused.e.g. YUY2 ring is sending and IBC store is disabled

    //USB DMA list fields
    MMP_BOOL   bWaitDMADone;
    MMP_USHORT max_dsize;//max payload data size for a USB transfer. See Figure 2-10(Bulk) or 2-13(ISO), UVC 1.1 SPEC.
    MMP_ULONG  usb_dma_len; //the size of AIT HW USB DMA list in bytes for this DMA process.
    volatile MMP_UBYTE *pNextPayload; //the address for next incoming transfer.

    TX_FRAME_BUF fb;
} USB_TRANSFER_INFO;

//consider using UsbTx for shorter name.
static USB_TRANSFER_INFO UsbTransfer;

#if USB_UVC_BULK_EP
MMP_ULONG usb_uvc_fill_padding_data(MMP_ULONG framelength)
{
    //20140108@Gason,for unknown video header.
    MMP_USHORT redundent = 0;
    redundent = (framelength+FRAME_PAYLOAD_HEADER_SZ) % (HS_TX_MAX_PK_SIZE*TX_PER_FRAME-12);//(UVC_DMA_SIZE-12);
    if( redundent > 0 && ((redundent + 12) & 0x1FF)==0 )
        return framelength+32;

    return framelength;
}
#endif

static void usb_uvc_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq,
                                        MMP_ULONG flag, MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h,
                                        MMP_USHORT type, MMP_USHORT framerate)
{
    struct _UVC_H264_PH *header = (struct _UVC_H264_PH *) frame_ptr ;
    if(header){
        header->wVersion = 0x0100 ;
        header->wHeaderLen = UVC_H264_PH_LEN ; // not include dwPayloadSize
        switch(type){
        case ST_YUY2:
            header->dwStreamType = 0x32595559 ;
            break;
        case ST_NV12:
            header->dwStreamType = 0x3231564E ;
            break;
        case ST_H264:
            header->dwStreamType = 0x34363248 ;
            break;         
        default:
            header->dwStreamType = 0x34363248 ;
            break;
        }
        header->wImageWidth = w ;
        header->wImageHeight = h ;
        header->dwFrameRate = (10000000 / framerate);
#if ALIGN_PAYLOAD==0        
        header->dwFrameSeq = frameseq ;
        header->wReserved = 0 ;
#endif
        header->dwTimeStamp = timestamp ;
        header->wDelay = 0 ;
        header->dwPayloadSize = framelength ;
        #if 0
        RTNA_DBG_Str3("-FrameCount:");
        RTNA_DBG_Long3(header->dwFrameSeq);
        RTNA_DBG_Str3("\r\n");
        RTNA_DBG_Str3("-PayloadSize:");
        RTNA_DBG_Long3(header->dwPayloadSize);
        RTNA_DBG_Str3("\r\n");
        #endif
    }
}

static void usb_skype_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq,
                                          MMP_ULONG flag, MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h,
                                          MMP_USHORT type, MMP_USHORT framerate)
{
    struct _SKYPE_H264_PH *header = (struct _SKYPE_H264_PH *) frame_ptr ;
    if(header){
        header->dwFrameSizeWithId = SKYPE_PAYLOAD_ID | ((framelength + FRAME_PAYLOAD_HEADER_SZ) << 8) ;
        header->dwFrameSeq = frameseq ;
        //        header->dwFlag = flag ;
        header->dwPayloadOffset = FRAME_PAYLOAD_HEADER_SZ ; // OOXX should fixed
        header->dwTimeStamp = timestamp ;
#if ALIGN_PAYLOAD==0        
        //        header->wImageWidth = w ;
        //        header->wImageHeight = h ;
        //        header->wStreamType = type ;
#endif
        //        header->wFrameRate = framerate;
        header->dwPayloadSize = framelength ;
    }
}

static void usb_frameh264_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq,
                                              MMP_ULONG flag, MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h,
                                              MMP_USHORT type, MMP_USHORT framerate)
{
    struct _FRAME_H264_PH *header = (struct _FRAME_H264_PH *) frame_ptr ;
#if XU_FRAMEBASE_CAPTURE
    if((gFramebaseCap.JPEG) && (gbStillCaptureEvent == STILL_IMAGE_SENDING)){
        type = ST_CaptureJPG;
    }
#endif
    if(header){
        header->wVersion = UVC_H264_VER ;
        header->wImageOffset = UVC_H264_PH_LEN ; // not include dwPayloadSize
        header->wStreamType = type ;
        header->wImageWidth = w ;
        header->wImageHeight = h ;
        header->wFrameRate = framerate;
        header->dwFrameSeq = frameseq ;
        header->dwTimeStamp = timestamp ;
        header->dwFrameSize = framelength;
        #if USB_UVC_BULK_EP
        header->dwPayloadSize = usb_uvc_fill_padding_data(ALIGN32(framelength));//20140108@Gason,for unknown video header.
        #else
        header->dwPayloadSize = ALIGN32(framelength); // force frame length to 32 bytes alignment for Linux UVC driver
        #endif
        PH_SET_STREAM_ID(header->dwFlag, 0);  // set 0 for streamviwer tools
        PH_SET_STREAM_TYPE(header->dwFlag, (MMP_UBYTE)(flag));
        PH_SET_TX_CTL(header->dwFlag, 1); // use to sepcified if sent by USB.
#if (MotionDetection == 1)
        {
            extern void COLOR_CopyAEAcc(MMP_ULONG *addr);
            COLOR_CopyAEAcc((MMP_ULONG *) header);
        }
#endif
    }
}

static void usb_skype_uvc_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq,
                                              MMP_ULONG flag, MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h,
                                              MMP_USHORT type, MMP_USHORT framerate)
{
    struct _SKYPE_UVC_H264_PH *header = (struct _SKYPE_UVC_H264_PH *) frame_ptr ;
    if(header){
#if ALIGN_PAYLOAD==0        
        header->dwReserved1 = 0 ;  // Skip offset data for USBIF UVC 1.1 H.264 payload
        header->wReserved2 = 0 ;  // Skip offset data for USBIF UVC 1.1 H.264 payload
#endif
        header->wVersion = 0x0100 ;
        header->wHeaderLen = UVC_H264_PH_LEN - 6 ; // not include dwPayloadSize
        switch(type){
        case ST_YUY2:
            header->dwStreamType = 0x32595559 ;
            break;
        case ST_NV12:
            header->dwStreamType = 0x3231564E ;
            break;
        case ST_H264:
            header->dwStreamType = 0x34363248 ;
            break;         
        default:
            header->dwStreamType = 0x34363248 ;
            break;
        }
        header->wImageWidth = w ;
        header->wImageHeight = h ;
        header->dwFrameRate = (10000000 / framerate);
        header->dwTimeStamp = timestamp ;
        header->wDelay = 0 ;
        header->dwPayloadSize = framelength ;
    }
}


void usb_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq, MMP_ULONG flag,
                             MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h, MMP_USHORT framerate,
                             MMP_UBYTE format_type, MMP_UBYTE ubPipe)
{
    MMP_UBYTE   ph_type = PIPE_PH_TYPE_NA;
    const STREAM_CFG  *cur_pipe = usb_get_stream_cfg();

    if(ubPipe == PIPE_0){
        ph_type = cur_pipe->pipe0_ph_type;
    }
    else if(ubPipe == PIPE_1){
        ph_type = cur_pipe->pipe1_ph_type;
    }
    else if(ubPipe == PIPE_2){
        ph_type = cur_pipe->pipe2_ph_type;
    }
    else if(ubPipe == PIPE_G){
        ph_type = PIPE_PH_TYPE_3;
    }
#if SUPPORT_PIPE_Y
    else if(ubPipe == PIPE_Y){
        ph_type = PIPE_PH_TYPE_3;
    }
#endif
#if SUPPORT_AIT845x_MD
    else if(ubPipe == PIPE_M){
        ph_type = PIPE_PH_TYPE_3;
    }
#endif
#if (SUPPORT_MP4) || (SUPPORT_MTS)
    else if(ubPipe == PIPE_AUD){
        ph_type = PIPE_PH_TYPE_3;
    }
#endif
    else {
        ph_type = cur_pipe->pipe1_ph_type;
    }

#if MTS_MUXER_EN
    if(ST_H264 == format_type){
        format_type = (MMPF_VIDMGR_GetMtsMuxModeEnable()) ? ST_M2TS : ST_H264;
    }
#endif

#if USB_FRAMEBASE_DUAL_H264_STREAM
    if((gbCurH264Type == FRAMEBASE_DUAL_H264) || (gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG)) 
        if(ST_H264 == format_type){
            if(ubPipe)
                format_type = ST_H264_Sub;
            else
                format_type = ST_H264;
        }
#endif

#if (KITE_ONLY_VIDEO_PATCH == 1)
    if(ph_type == PIPE_PH_TYPE_1){
        usb_uvc_fill_payload_header(frame_ptr, ALIGN32(framelength), frameseq, flag, timestamp, w, h, format_type,
                                    framerate, framelength);
    }
    else
#endif
    #if XU_FRAMEBASE_CAPTURE
    if((gFramebaseCap.format == CF_YUY2/*1*/) || (gFramebaseCap.format == CF_MJPEG/*2*/))
        ph_type = PIPE_PH_TYPE_3;
#endif
    if(ph_type <= PIPE_PH_TYPE_4 && (ph_type > PIPE_PH_TYPE_NA)){
        static void (* const fill_ph_functions[4])(MMP_UBYTE *, MMP_ULONG, MMP_ULONG, MMP_ULONG, MMP_ULONG,
                                                   MMP_USHORT w, MMP_USHORT h, MMP_USHORT, MMP_USHORT) =
        {
        usb_uvc_fill_payload_header,
        usb_skype_fill_payload_header,
        usb_frameh264_fill_payload_header,
        usb_skype_uvc_fill_payload_header
        };
        fill_ph_functions[ph_type - 1](frame_ptr, framelength, frameseq, flag, timestamp, w, h, format_type, framerate);
    }
    else{
        dbg_printf(3, "[ERR] unsupported payload format pipe%d, type%d\r\n", ubPipe, ph_type);
    }
}


#if SUPPORT_SKYPE_OLD_HEADER
void usb_skype_fill_old_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq,
                                       MMP_ULONG timestamp)
{
    frame_ptr[0] = SKYPE_PAYLOAD_ID;
    frame_ptr[1] = framelength;
    frame_ptr[2] = framelength >> 8;
    frame_ptr[3] = framelength >> 16;
    //    frame_ptr[4]=frameseq;
    //    frame_ptr[5]=frameseq>>8;
    //    frame_ptr[6]=frameseq>>16;
    //    frame_ptr[7]=frameseq>>24;
    //    frame_ptr[8]=0x00;
    //    frame_ptr[9]=0x00;
    //    frame_ptr[10]=0x00;
    //    frame_ptr[11]=0x00;// last fragment = 1
    frame_ptr[12] = 20;
    frame_ptr[13] = 0x00;
    frame_ptr[14] = 0x00;
    frame_ptr[15] = 0x00;
    //    frame_ptr[16]=timestamp;
    //    frame_ptr[17]=timestamp>>8;
    //    frame_ptr[18]=timestamp>>16;
    //    frame_ptr[19]=timestamp>>24;
}
#endif

volatile MMP_UBYTE * usb_vc_fill_header(volatile MMP_UBYTE *ptr, MMP_UBYTE bfh, MMP_ULONG pts, MMP_ULONG stc,
                                        MMP_USHORT sofnum)
{
    UVC_VIDEO_PAYLOAD_HEADER *pUVCHeader = (UVC_VIDEO_PAYLOAD_HEADER *) ptr ;

    // Get current system clock
    if(stc == 0){
        stc = MMPF_BSP_GetTick() * glCPUFreq + MMPF_BSP_GetTickClock() ;
    }

    pUVCHeader->bHLE = sizeof(UVC_VIDEO_PAYLOAD_HEADER);
    pUVCHeader->bBFH = bfh;
#if USE_PACKED_PAYLOAD_HEADER
    pUVCHeader->bPTS = pts;
    pUVCHeader->bSCR = stc;
    pUVCHeader->bSOFNUM = sofnum;
#else
    pUVCHeader->bPTS[0] = pts & 0xFF ;
    pUVCHeader->bPTS[1] = (pts >> 8) & 0xFF ;
    pUVCHeader->bPTS[2] = (pts >> 16) & 0xFF ;
    pUVCHeader->bPTS[3] = (pts >> 24) & 0xFF ;
    pUVCHeader->bSCR[0] = stc & 0xFF ;
    pUVCHeader->bSCR[1] = (stc >> 8) & 0xFF ;
    pUVCHeader->bSCR[2] = (stc >> 16) & 0xFF ;
    pUVCHeader->bSCR[3] = (stc >> 24) & 0xFF ;
    pUVCHeader->bSOFNUM[0] = (sofnum >> 0) & 0xFF ;
    pUVCHeader->bSOFNUM[1] = (sofnum >> 8) & 0xFF ;
#endif
    return ptr + pUVCHeader->bHLE ;
}

#if UVC_MOVE_DMA_EN == 0
#define usb_vc_wait_dma_done(id, timeout) MMP_ERR_NONE
#else
volatile MMP_BOOL    m_bUvcDmaMoveWorking = MMP_FALSE;
void _dma_status_callback(void)
{
    m_bUvcDmaMoveWorking = MMP_FALSE;

    //RTNA_DBG_Str(3, "[dma done]\r\n");
}

MMP_ERR usb_vc_trig_dma_move(MMP_ULONG ulSrcaddr, MMP_ULONG ulDstaddr, MMP_ULONG ulCount)
{
    if(m_bUvcDmaMoveWorking == MMP_TRUE){
        RTNA_DBG_Str(0, "UVC DMA busy\r\n");
        return MMP_DMA_ERR_BUSY;
    }

    m_bUvcDmaMoveWorking = MMP_TRUE;

#if (CHIP == VSN_V2)
    MMPF_DMA_RotateData0(ulSrcaddr, ulDstaddr, ulCount, ulCount, ulCount, 1, DMA_R_BPP_8 | DMA_R_BLK_16X16,
                         DMA_R_MIRROR_DISABLE, _dma_status_callback);
#endif

#if (CHIP == P_V2)
    MMPF_DMA_MoveData1(ulSrcaddr, ulDstaddr, ulCount, _dma_status_callback);
#endif

    return MMP_ERR_NONE;
}

MMP_ERR usb_vc_wait_dma_done(MMPF_DMA_R_ID DMA_ID, MMP_ULONG timeout) // timeout is loop count
{
#if 1 //(CHIP == VSN_V2)
    MMP_ULONG dma_timeout = 0 ;
    do{
        if(m_bUvcDmaMoveWorking == MMP_FALSE)
            break;
    }
    while(dma_timeout++ < timeout);

    if(dma_timeout >= timeout){
        AITPS_DMA   pDMA = AITC_BASE_DMA;
        //MMP_USHORT  DMA_INT = DMA_INT_R0 ;

        RTNA_DBG_PrintShort(0, pDMA->DMA_INT_CPU_EN);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_SRC_ADDR);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_DST_ADDR);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_SRC_OFST);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_DST_OFST);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_PIX_W);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_PIX_H);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_CTL);
        RTNA_DBG_PrintLong(0, pDMA->DMA_R[DMA_ID].DMA_R_MIRROR_EN);

        RTNA_DBG_Str(0, "---DMA rotate timeout---\r\n");
        return MMP_DMA_ERR_BUSY ;
    }
#endif

#if 0 //(CHIP == P_V2)
AITPS_DMA   pDMA = AITC_BASE_DMA;   
MMP_ULONG dma_timeout = 0 ;
MMP_USHORT DMA_INT = DMA_INT_M1 ;
if(DMA_ID==MMPF_DMA_M_0) {
    DMA_INT = DMA_INT_M0 ;
}
do {
    if((pDMA->DMA_INT_CPU_SR & DMA_INT)|
    ((pDMA->DMA_INT_CPU_EN & DMA_INT)==0)&&((pDMA->DMA_M[DMA_ID].DMA_M_LEFT_BYTE)==0)) {
        pDMA->DMA_INT_CPU_SR = DMA_INT;
        break;
    }
} while (dma_timeout++ < timeout ) ; 
if(dma_timeout >= timeout) {
    //#if CHIP==P_V2
    //RTNA_DBG_Short(0,(DMA_ID==MMPF_DMA_M_0)?pDMA->DMA_M0_EN:pDMA->DMA_M1_EN); 
    //#endif            
    //RTNA_DBG_Short(0,pDMA->DMA_INT_CPU_EN);
    //RTNA_DBG_Long(0,pDMA->DMA_M[DMA_ID].DMA_M_SRC_ADDR);
    //RTNA_DBG_Long(0,pDMA->DMA_M[DMA_ID].DMA_M_DST_ADDR);
    //RTNA_DBG_Long(0,pDMA->DMA_M[DMA_ID].DMA_M_BYTE_CNT);
    //RTNA_DBG_Long(0,pDMA->DMA_M[DMA_ID].DMA_M_LEFT_BYTE);
    RTNA_DBG_Str(0, "---DMA move timeout---\r\n");
    return MMP_DMA_ERR_BUSY ; 
}
#endif

    return MMP_ERR_NONE ;
}
#endif


//frame: one SOF/uSOF
//packet: The min transfer unit in one IN token
//payload: The min transfer unit which include one USB payload header, 12Bytes
//         ISO   3  packets
//         BULK  32 packets
//image: one whole picture for YUV or MJPEG, one I or P frame for H264
#if STREAM_DMA_BLK_VER == 3
//prepare next USB payload information for USB transfer from STREAM_DMA_BLK list
//to avoid mixed up with AIT 32-byte payload header, use the USB term transfer instead.
//It was previously called move_packet.
static MMP_ULONG _uvc_prepare_next_transfer(STREAM_DMA_BLK *dma_blk, MMP_UBYTE sti_mode, MMP_UBYTE *pad_app3_header,
                                            MMP_ULONG *sent_size)
{
    MMP_ULONG data_addr = 0, left_size;
    MMP_ULONG i, payload_count, residual, tx_size = 0;
    MMP_ULONG dsize = TX_PER_FRAME*HS_TX_MAX_PK_SIZE - sizeof(UVC_VIDEO_PAYLOAD_HEADER);

    *sent_size = 0 ;

    left_size = dma_blk->blk_size - UsbTransfer.tx_len;
    payload_count = left_size / dsize;
    residual = left_size % dsize;
    if(residual > 0)
        payload_count++;

    if(payload_count > UVC_DMA_PAYLOAD_NUM)
        payload_count = UVC_DMA_PAYLOAD_NUM;

    //what if dma_blk->blk_size==0? ok
    //what if left_size==0?*sent_size=0, data_addr?

    if(pad_app3_header && dma_blk->header_len){
        if((UsbTransfer.tx_len == 0) && (dma_blk->blk_size)){
            data_addr = (MMP_ULONG) pad_app3_header;// App3 marker
            *sent_size += dma_blk->header_len;// +App3 marker
            //*sent_size += sizeof(UVC_VIDEO_PAYLOAD_HEADER);//12;
            UsbTransfer.tx_cnt++;
            dma_blk->header_len = 0;
            return data_addr;
        }
    }

    if((dma_blk->blk_size > UsbTransfer.tx_len)){
        data_addr = (MMP_ULONG) UsbTransfer.cur_addr;
        for(i = 0;i < payload_count ;i++){
            left_size = dma_blk->blk_size - UsbTransfer.tx_len;

            if(dsize >= left_size){
                tx_size = left_size ;
            }
            else{
                tx_size = dsize ;
            }

            *sent_size += (tx_size /*+ sizeof(UVC_VIDEO_PAYLOAD_HEADER)*/);// UVC payload header must send in every payload

            UsbTransfer.cur_addr += tx_size;
            UsbTransfer.tx_len += tx_size;
            UsbTransfer.tx_cnt++;
        }

        if(*sent_size == 0)
            data_addr = 0;
    } else 
        UsbTransfer.tx_len = 0;

    if(*sent_size == 0)
        data_addr = 0;

    return data_addr;
}
// return 
// 1 : last packet
// 0 : continue
#else
MMP_ULONG usb_vc_move_packet(STREAM_DMA_BLK *dma_blk, MMP_UBYTE endbit, MMP_UBYTE sti_mode,
                             MMP_UBYTE *pad_app3_header, MMP_ULONG *sent_size)
{
    MMP_UBYTE i;
    volatile MMP_UBYTE *cur_pt[UVC_DMA_3K_NUM];
    MMP_ULONG data_addr = 0, left_size;
#if STREAM_DMA_BLK_VER == 1
    cur_pt[0] = (volatile MMP_UBYTE *) dma_blk->dma_buf[dma_blk->tx_cnt & 1] ;
#else
    cur_pt[0] = (volatile MMP_UBYTE *) Transfer.dma_buf[0];
#endif
#if UVC_DMA_3K_NUM==2
    cur_pt[1] = (volatile MMP_UBYTE *) Transfer.dma_buf[1];
#endif

#if 0
RTNA_DBG_Str3("DMA.Addr:");
RTNA_DBG_Long3((MMP_ULONG)cur_pt);
RTNA_DBG_Str3("\r\n");
#endif

    *sent_size = 0 ;

    for(i = 0;i < UVC_DMA_3K_NUM ;i++){
        usb_vc_fill_header(cur_pt[i],
                           endbit |
                           BFH_BIT(BFH_PTS) |
                           BFH_BIT(BFH_SCR) |
                           UvcSampleBuilder.toggle |
                           (sti_mode ? BFH_BIT(BFH_STI) : 0),
                           UsbTransfer.PTS, 0, USB_GET_SOF_NUM());

        // Double buffer need to push last packet out.
#if STREAM_DMA_BLK_VER == 1
        if((dma_blk->tx_len == 0) && (dma_blk->blk_size)) 
#else
            if((UsbTransfer.tx_len == 0) && (dma_blk->blk_size)) 
#endif
            {
                if(pad_app3_header && dma_blk->header_len){
#if UVC_MOVE_DMA_EN                
                    int j;

                    for(j = 0;j < dma_blk->header_len;j++){
                        cur_pt[0][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + j] = pad_app3_header[j] ;
                    }
#else              
                    data_addr = (MMP_ULONG) pad_app3_header;
                    *sent_size += dma_blk->header_len;
                    *sent_size += sizeof(UVC_VIDEO_PAYLOAD_HEADER);//12;
#if STREAM_DMA_BLK_VER == 1
                    dma_blk->tx_cnt++;
#else
                    Transfer.tx_cnt++;
#endif
                    dma_blk->header_len = 0;
                    return data_addr;
#endif
                }
            }

        if(dma_blk->blk_size){
            MMP_ULONG tx_size = 0 , tx_header_len = 0;


#if STREAM_DMA_BLK_VER == 1
            left_size = dma_blk->blk_size - dma_blk->tx_len;

            if(dma_blk->tx_len >= dma_blk->blk_size){
                return data_addr;
            }

            if(dma_blk->max_dsize >= left_size){
                tx_size = left_size ;
            }
            else{
                tx_size = dma_blk->max_dsize ;
            }  
            if((!dma_blk->tx_len) && (i == 0))
#else
                left_size = dma_blk->blk_size - Transfer.tx_len;
            if(Transfer.tx_len >= dma_blk->blk_size){
                return data_addr;//return last packet addr
            }

            if(Transfer.max_dsize >= left_size){
                tx_size = left_size ;
            }
            else{
                tx_size = Transfer.max_dsize ;
            }  
            if((!Transfer.tx_len) && (i == 0))
#endif
            {
                tx_header_len = dma_blk->header_len ;
                if(tx_header_len){
#if STREAM_DMA_BLK_VER == 1
                    if((tx_size + tx_header_len) > dma_blk->max_dsize){
                        // to avoid transfer packet size > maximum payload size
                        tx_size = (dma_blk->max_dsize - tx_header_len) ;
                    }
#else
                    if((tx_size + tx_header_len) > Transfer.max_dsize){
                        // to avoid transfer packet size > maximum payload size
                        tx_size = (Transfer.max_dsize - tx_header_len) ;
                    }
#endif
                }
            }
            else{
                tx_header_len = 0 ;
            }
#if UVC_MOVE_DMA_EN
            // First 3K use DMA1
            if(i == 0){
                if((dma_blk->flag & DUMMY_DMA_BLK) == 0){
                    // check if dummy block to skip Move DMA function
#if STREAM_DMA_BLK_VER == 1
#if 1 //julian dbg only
                    usb_vc_trig_dma_move((MMP_ULONG) dma_blk->cur_addr,
                                         (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                         tx_size);
#else
                    if(MMPF_DMA_MoveData1((MMP_ULONG) dma_blk->cur_addr,
                                          (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                          tx_size, 0)){
                        RTNA_DBG_Str(0, "MMPF_DMA_MoveData1 Fail\r\n");
                    }
#endif
#else
#if 1 //julian dbg only
#if 0
if (usbframecount < 3) {
    dbg_printf(2, "move0 %X to %X sz%d\r\n", (MMP_ULONG)Transfer.cur_addr, (MMP_ULONG)&cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER)+tx_header_len], tx_size);
}
#endif
                    usb_vc_trig_dma_move((MMP_ULONG) Transfer.cur_addr,
                                         (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                         tx_size);
#else
                    if( MMPF_DMA_MoveData1((MMP_ULONG) Transfer.cur_addr,
                                          (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                          tx_size, 0)){
                        RTNA_DBG_Str(0, "MMPF_DMA_MoveData1 Fail\r\n");
                    }
#endif
#endif
                }
            }
#if UVC_DMA_3K_NUM > 1
            else{
                // Second 3K use DMA0
#if STREAM_DMA_BLK_VER == 1
                if((dma_blk->flag & DUMMY_DMA_BLK) == 0){
                    // check if dummy block to skip Move DMA function
#if 1//T.B.D, need another dma
                    //usb_vc_trig_dma_move((MMP_ULONG)dma_blk->cur_addr, (MMP_ULONG)&cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER)+tx_header_len], tx_size);
#else
                    if(MMPF_DMA_MoveData0((MMP_ULONG) dma_blk->cur_addr,
                                          (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                          tx_size, NULL, NULL)){
                        RTNA_DBG_Str(0, "MMPF_DMA_MoveData0 Fail\r\n");
                    }
#endif
                }
#else
                if((dma_blk->flag & DUMMY_DMA_BLK) == 0){
                    // check if dummy block to skip Move DMA function
                    //dbg_printf(2, "move1 %X to %X sz%d\r\n", (MMP_ULONG)UsbPacketInfo.cur_addr, (MMP_ULONG)&cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER)+tx_header_len], tx_size);
#if 1 //T.B.D, need another dma
                    //usb_vc_trig_dma_move((MMP_ULONG)UsbPacketInfo.cur_addr, (MMP_ULONG)&cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER)+tx_header_len], tx_size);
#else
                    if(MMPF_DMA_MoveData0((MMP_ULONG) Transfer.cur_addr,
                                          (MMP_ULONG) & cur_pt[i][sizeof(UVC_VIDEO_PAYLOAD_HEADER) + tx_header_len],
                                          tx_size, NULL, NULL)){
                        RTNA_DBG_Str(0, "MMPF_DMA_MoveData0 Fail\r\n");
                    }
#endif
                }
#endif
            }
#endif
#endif// UVC_MOVE_DMA_EN

            // UVC header must send in every UVC_DMA_3K
            *sent_size += sizeof(UVC_VIDEO_PAYLOAD_HEADER);
            *sent_size += (tx_size + tx_header_len) ; // + App3 marker

#if STREAM_DMA_BLK_VER == 1
            if(i == 0){
#if UVC_MOVE_DMA_EN
                data_addr = (MMP_ULONG) cur_pt[0];
#else
                data_addr = dma_blk->cur_addr;
#endif
            }
            dma_blk->cur_addr += tx_size;
            dma_blk->tx_len += tx_size;
            dma_blk->tx_cnt++;
#else
            if(i == 0){
#if UVC_MOVE_DMA_EN
                data_addr = (MMP_ULONG) cur_pt[0];
#else
                data_addr = (MMP_ULONG) Transfer.cur_addr;
#endif
            }
            Transfer.cur_addr += tx_size;
            Transfer.tx_len += tx_size;
            Transfer.tx_cnt++;
#endif
        }
    }
    return data_addr;
}
#endif
#if STREAM_DMA_BLK_VER == 3
//refer to Figure 2-10, UVC1.1 SPEC. The payload here is for USB transfer, not AIT payload or encoding format.
static MMP_ULONG _uvc_tx_fill_payload_header(MMP_UBYTE endbit, MMP_UBYTE sti_mode)
{
    volatile MMP_UBYTE *cur_pt;
#if UVC_DMA_3K_NUM==2
    Transfer.bPhToggle ^= 1;//if UVC_DMA_3K_NUM==1, the buf1 and buf2 are the same
#endif
    cur_pt = (volatile MMP_UBYTE *) UsbTransfer.ph_buf[UsbTransfer.bPhToggle];

    usb_vc_fill_header(cur_pt,
                       endbit |
                       BFH_BIT(BFH_PTS) |
                       BFH_BIT(BFH_SCR) |
                       UsbTransfer.toggle |
                       (sti_mode ? BFH_BIT(BFH_STI) : 0),
                       UsbTransfer.PTS, 0, USB_GET_SOF_NUM());

    return (MMP_ULONG) cur_pt ;
}
#else
MMP_ULONG usb_vc_fill_empty_packet(STREAM_DMA_BLK *dma_blk, MMP_UBYTE endbit, MMP_UBYTE sti_mode)
{
    volatile MMP_UBYTE *cur_pt ;
    MMP_UBYTE uvcdma_index;

    uvcdma_index = 0;//UsbPacketInfo.tx_packets & (UVC_DMA_3K_NUM-1);

#if STREAM_DMA_BLK_VER == 1
    cur_pt = (volatile MMP_UBYTE *) dma_blk->dma_buf[uvcdma_index] ;
#else
    cur_pt = (volatile MMP_UBYTE *) Transfer.dma_buf[uvcdma_index] ;
#endif

    usb_vc_fill_header(cur_pt,
                       endbit |
                       BFH_BIT(BFH_PTS) |
                       BFH_BIT(BFH_SCR) |
                       UvcSampleBuilder.toggle |
                       (sti_mode ? BFH_BIT(BFH_STI) : 0),
                       PTS_UVC, 0, USB_GET_SOF_NUM());
#if STREAM_DMA_BLK_VER == 1
    dma_blk->tx_cnt++;
#else
    Transfer.tx_cnt++;
#endif
    return (MMP_ULONG) cur_pt ;
} 
#endif//STREAM_DMA_BLK_VER == 3
extern void MMPF_USB_WaitDMA(void) ;
#if (STREAM_DMA_BLK_VER == 3)
extern MMP_ULONG glWaitDMA;
/* xsize use MMP_USHORT, therefore maximum 64K*/
static __inline void _uvc_tx_send_payload(MMP_ULONG cur_pt, MMP_ULONG xsize, MMP_USHORT endbit, MMP_UBYTE sti_mode)
{
    MMP_ULONG   header_addr, send_data_addr;
    MMP_ULONG   payload_cnt, residue, tx_payload_size, max_pkrdy_transfer_size;
    MMP_USHORT  i;
    MMP_BOOL    last_payload;
    MMP_ULONG   dsize = TX_PER_FRAME*HS_TX_MAX_PK_SIZE - sizeof(UVC_VIDEO_PAYLOAD_HEADER);

#if USB_UVC_BULK_EP
    max_pkrdy_transfer_size = xsize;//bulk mode need to add pktrdy in every packet (512B)
#else//ISO mode
    max_pkrdy_transfer_size = UVCTxFIFOSize;//ISO mode only need to add pktrdy in every payload (3KB)
#endif
    MMPF_USB_WaitDMA(); //sean@2010_10_04
    if(glWaitDMA) {
        header_addr = 0;
        xsize = 0;
        dbg_printf(3,"UVC TX Send Payload Reset!!!\r\n");
        return;
    }

    header_addr = _uvc_tx_fill_payload_header(endbit, sti_mode);

    if(endbit == UVC_EOF){
        //send the last packet of frame. It is 12B UVC payload header
        UsbDmaTxConfigUVCPayload(PCCAM_TX1_EP_ADDR, (MMP_ULONG) header_addr, 0, HS_TX_MAX_PK_SIZE, header_addr,
                                 MMP_TRUE);
    }
    else{
        payload_cnt = xsize / dsize;// xsize/8180
        residue = xsize % dsize;
        if(residue)
            payload_cnt++;

        send_data_addr = cur_pt;

        last_payload = MMP_FALSE;
        for(i = 0;i < payload_cnt;i++){
            if(dsize >= xsize){
                tx_payload_size = xsize;
                last_payload = MMP_TRUE;
            }
            else{
                tx_payload_size = dsize;
            }
            UsbDmaTxConfigUVCPayload(PCCAM_TX1_EP_ADDR, (MMP_ULONG) send_data_addr, tx_payload_size,
                                     HS_TX_MAX_PK_SIZE, header_addr, last_payload);
            send_data_addr += tx_payload_size;
            xsize -= tx_payload_size;
        }
    }
}
#else    
__inline void usb_vc_send_packet(MMP_ULONG cur_pt, MMP_USHORT xsize)
{
    MMP_ULONG header_addr;

    MMPF_USB_WaitDMA(); //sean@2010_10_04

    //VAR_W(3, xsize)
    if((xsize >= 12) && (xsize <= UVCTxFIFOSize * UVC_DMA_3K_NUM)){
        MMP_ULONG total_cnt, residue;

        //need to revise the payload usage
#if UVC_MOVE_DMA_EN
        header_addr = NULL;
#else
#if STREAM_DMA_BLK_VER == 1
        header_addr = (MMP_ULONG) dma_blk->dma_buf[0];
#else
        header_addr = (MMP_ULONG) Transfer.dma_buf[0];
#endif
#endif

        if(xsize == sizeof(UVC_VIDEO_PAYLOAD_HEADER))//if the size is 12, it must be uvc payload header
            header_addr = NULL;

        total_cnt = xsize / UVCTxFIFOSize;
        residue = xsize % UVCTxFIFOSize;
        if(residue)
            total_cnt++;

        UsbDmaTxConfigUVCPayload(PCCAM_TX1_EP_ADDR, (MMP_ULONG) cur_pt, xsize, UVCTxFIFOSize, total_cnt, header_addr);
        residue = xsize - total_cnt * sizeof(UVC_VIDEO_PAYLOAD_HEADER) /*12 bytes*/;
    }
    else{
        dbg_printf(3, "[ERR] Unexpected size\r\n");
    }
    // Request next packet
    //     MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_USBOP, MMPF_OS_FLAG_SET);
}
#endif
#define DBG_RING_BLK 0//debug adding DMA block for ring
#if DBG_RING_BLK
#define DRBP(...) if (usbframecount == 1) dbg_printf(3, __VA_ARGS__)
#define DRB(x) x
MMP_USHORT dbg_blk = 0;
MMP_ULONG dbg_tx_size[200];
MMP_ULONG yuv_addr = 0;
#else
#define DRBP(...)
#define DRB(x)
#endif
extern volatile MMP_BOOL gbIBCWritting;

//maybe use uvc_tx_init instead?
//The name with _tx_ means it requires the knowledge of USB_TRANSFER_INFO, no STREAM_DMA_BLK knowledge is needed.
//The functions which requires both knowledge are named as just uvc_
static void _uvc_tx_init(MMP_USHORT max_dsize, MMP_ULONG dmabuf1, MMP_ULONG dmabuf2)
{
    UsbTransfer.max_dsize = max_dsize;
    UsbTransfer.cur_addr = 0;
    UsbTransfer.tx_len = 0;
    UsbTransfer.tx_cnt = 0;
#if STREAM_DMA_BLK_VER == 2
    UsbTransfer.dma_buf[0] = dmabuf1;
    UsbTransfer.dma_buf[1] = dmabuf2;
#elif STREAM_DMA_BLK_VER == 3
    UsbTransfer.ph_buf[0] = dmabuf1;
    UsbTransfer.ph_buf[1] = dmabuf2;
    UsbTransfer.bPhToggle = 0;
#endif
    UsbTransfer.bSrcPause = MMP_FALSE;
}

static void _uvc_tx_set_next(MMP_ULONG next_ptr)
{
    UsbTransfer.cur_addr = next_ptr;
    UsbTransfer.tx_len = 0;
    UsbTransfer.tx_cnt = 0;
}

#if SPEED_UP_PREVIEW_FRAME_RATE
static MMP_BOOL _uvc_tx_has_ibc_data(MMPF_IBC_PIPEID pipe_path)
{
    MMP_BOOL hasData = 0;
    MMP_USHORT max_tx_size;
#if STREAM_DMA_BLK_VER==2
    max_tx_size = UsbTransfer.max_dsize * UVC_DMA_3K_NUM;
#elif STREAM_DMA_BLK_VER==3
    max_tx_size = UsbTransfer.max_dsize * UVC_DMA_PAYLOAD_NUM;
#endif
    if(pipe_path < MMPF_IBC_PIPE_MAX){
        //found an YUY2 format, assume there is one YUY2 only.
        //revise this to a loop if 2+ YUY2 pipes are needed.
        MMP_ULONG th;
        MMP_ULONG bytecount;
        MMP_ULONG ring_frame_size;

        bytecount = MMPF_IBC_GetRingBufWrPtr(pipe_path);
        // 1/6 frame. Set th by time. 30ms/6 ~= 5ms
        //th = ((FRAME_PAYLOAD_HEADER*)MMPF_Video_CurRdPtr(pipe))->SKYPE_UVC_H264_PH.dwPayloadSize/6;

        // set threshold by size. almost near full and make the YUY2 overlapped and unusable.
        th = (PIPE_INFO(pipe_path, b)).slot_size - 10 * 1024;
        ring_frame_size = ((FRAME_PAYLOAD_HEADER *) MMPF_Video_CurRdPtr(pipe_path))->SKYPE_UVC_H264_PH.dwPayloadSize;

        if((UsbTransfer.fb.ProcSize == 0) && (bytecount > th)){
            //too late, skip this IBC frame.
            //hasData = 0;
        }
        else if((!gbIBCWritting) && ((ring_frame_size - UsbTransfer.fb.ProcSize) <= max_tx_size)){
            // last packet to be processed.
            hasData = 1;//send
        }
        else if(((!gbIBCWritting) && UsbTransfer.fb.ProcSize) || (UsbTransfer.fb.bKeepSending)){
                 hasData = 1;//send
            UsbTransfer.fb.bKeepSending = 1;//IBC byte count could be reset, so keep sending this frame no matter what..
        }
        else if(bytecount < ring_frame_size){
            if((bytecount >= (max_tx_size/*3048*/ + UsbTransfer.fb.ProcSize))){
                hasData = 1;//send
            }
        }
        if(gbStillCaptureEvent == STILL_IMAGE_TRIGGER){
            hasData = 1;
        }

        if(hasData){
            if((UsbTransfer.fb.phase == RT_TX_SENDING) && ((ring_frame_size - UsbTransfer.fb.ProcSize) < (36 * 1024))){
                MMPF_IBC_SetStoreEnable(pipe_path, MMP_TRUE);
                UsbTransfer.bSrcPause = MMP_FALSE;
            }
            if(UsbTransfer.fb.phase == RT_TX_ACTIVE){
                UsbTransfer.fb.phase = RT_TX_SENDING;//stop ibc store
                //MMPF_Video_UpdateRdPtrByPayloadLength();//move to H264 block send end
                MMPF_IBC_SetStoreEnable(pipe_path, MMP_FALSE);
                UsbTransfer.bSrcPause = MMP_TRUE;
            }
        }

        //debugging section
#if 0
if (hasData) {
    if (YuvPhase == 1) {
        MMPF_Timer_Log(&tlRd0);
    }
}
else {//this section is for debug purpose only.
    if (dbg_last_packetcount == packetcount) {
        dbg_packet_time_out++;
        if (dbg_packet_time_out == 30) {
            dbg_printf(3, " IBC:%d th:%d\r\n", bytecount, glRingBufProcSize + Transfer.max_dsize);
            dbg_packet_time_out = 0;
        }
    } else {
        dbg_packet_time_out = 0;//comment out this line for more debug messages.
    }
    dbg_last_packetcount = packetcount;
}
#endif
    }
    return hasData;
}
#endif

#if (STREAM_DMA_BLK_VER == 3)
static __inline MMP_UBYTE _uvc_send_blk(MMP_UBYTE sti_mode)
{
    STREAM_DMA_BLK *dma_blk;
    volatile MMP_UBYTE *cur_pt = 0;
    MMP_UBYTE   endbit = 0;
    MMP_ULONG  xsize = 0, send_size = 0;
    MMP_UBYTE   *app3_header = 0;
    PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;
    STREAM_CFG *stream_cfg = (STREAM_CFG *) usb_get_stream_cfg();
    MMP_UBYTE   pipe0_cfg,pipe1_cfg,pipe2_cfg;
    MMP_BOOL bHasNextBlk = MMP_FALSE;

    pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);
    pipe2_cfg = GET_PIPE_FORMAT(stream_cfg, 2);

    if(UvcSampleBuilder.initialized >= 2){
        dma_blk = MMPF_Video_GetCurBlk();

        // check if move DMA done.
        if(UsbTransfer.bWaitDMADone == 1){
            cur_pt = (volatile MMP_UBYTE *) UsbTransfer.pNextPayload;
            if(cur_pt == 0){
                if(((dma_blk->flag & DMA_BLK_RING) == 0) &&
                   (dma_blk->next_blk != 0) &&
                   ((dma_blk->next_blk->flag & (DMA_BLK_RING | DMA_BLK_SRC_IBC)) == (DMA_BLK_RING | DMA_BLK_SRC_IBC))){
                    //first block of IBC ring
                    UsbTransfer.fb.phase = RT_TX_ACTIVE;
                    UsbTransfer.fb.ProcSize = 0;
                    //The name payload refer to AIT internal image. e.g. an H.264 image in DRAM.
                    //Since the there would be 32-byte AIT payload header there (FRAME_PAYLOAD_HEADER),
                    //the function was named "byPayloadLength", not USB transfer payload.
                    MMPF_Video_UpdateRdPtrByPayloadLength(stream_cfg->pipe_en & PIPE_ASYNC);
                }

                bHasNextBlk = MMPF_Video_GoNextBlk();
                _uvc_tx_set_next(MMPF_Video_GetCurBlk()->blk_addr);

                if(!bHasNextBlk){
                    endbit = UVC_EOF;
                    xsize = 0;
                    usb_preclose_Tx_flag = 1;
                    //RTNA_DBG_Str(3, "=EOF1=\r\n");
                }
                else{
                    if((dma_blk->flag & DMA_BLK_RING) && ((dma_blk->next_blk->flag & DMA_BLK_RING) == 0)){
                        if(UsbTransfer.fb.phase == RT_TX_SENDING){
                            UsbTransfer.fb.phase = RT_TX_END;
                        }
                    }
                    xsize = UsbTransfer.usb_dma_len ; // Force zero frame first
                    gbdrawflag = 1 ;
                    MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 4, (void *) NULL);
                }
            }
            else{
                xsize = UsbTransfer.usb_dma_len;
            }

            UsbTransfer.bWaitDMADone = 0;
        }
        else{
            gbdrawflag = 1 ;
            //MMPF_OS_Sleep(1);//release the Task resource to low priority task.
            MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 6, (void *) NULL);
        }
    }  // end of if(UvcSample.packet_count >= 1)
    else{
        dma_blk = MMPF_Video_GetCurBlk();
        UsbTransfer.cur_addr = dma_blk->blk_addr;

        if(UsbTransfer.tx_len == 0){
            app3_header = MMPF_Video_GetBlkAppHeader(dma_blk);
        }
        cur_pt = (volatile MMP_UBYTE *) _uvc_prepare_next_transfer(dma_blk, sti_mode, app3_header, &send_size);
        if(cur_pt == 0){
            bHasNextBlk = MMPF_Video_GoNextBlk();
            _uvc_tx_set_next(MMPF_Video_GetCurBlk()->blk_addr);
            if(!bHasNextBlk){
                endbit = UVC_EOF;
                xsize = 0;
                usb_preclose_Tx_flag = 1;
                //RTNA_DBG_Str(3, "=EOF2=\r\n");
            }
            else{
                xsize = send_size; // Force zero frame first
                gbdrawflag = 1;
                MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 5, (void *) NULL);
            }
        }
        else{
            xsize = send_size;
        }
        UvcSampleBuilder.initialized++;
    }

#if (USING_STILL_METHOD_1==0)&&XU_FRAMEBASE_CAPTURE //Work-around:SECS has horizontal stripes on capture
    if((gbStillCaptureEvent == STILL_IMAGE_TRIGGER) && (dma_blk->flag & DMA_BLK_RING))
        endbit = UVC_EOF;
#endif

    //xsize should not include 12B header
    if((cur_pt) || (endbit == UVC_EOF)){
        /*
            dbg_printf(3,"======%x %x\r\n", usbframecount, UvcSample.packet_count);
            dbg_printf(3,"blk_addr, size: %x %x\r\n", dma_blk->blk_addr ,dma_blk->blk_size);
            dbg_printf(3,"cur_pt,  xsize: %x %x,%x\r\n", cur_pt, xsize, endbit);
            dbg_printf(3,"UsbPacketInfo : %x %x,%x %x\r\n", UsbPacketInfo.cur_addr, UsbPacketInfo.tx_len, UsbPacketInfo.tx_packets, UsbPacketInfo.bSrcPause);
        */
        _uvc_tx_send_payload((MMP_ULONG) cur_pt, xsize, endbit, sti_mode);
        //dbg_printf(3, "xsize = %d\r\n", xsize);
        UvcSampleBuilder.initialized++;
    }

    if(endbit == UVC_EOF){
        if(UvcSampleBuilder.nFrame == 20){
            ISP_IF_AE_SetFastMode(0); //do fastmode about 4 times AE calc.
            RTNA_DBG_Str3("Disable AE Fast Mode\r\n");
        }
        #if RAW_DATA_EN
        if(UvcSampleBuilder.nFrame == 30){
            extern MMP_BOOL gbEnAfter30P;
            gbEnAfter30P = 1;
        }
        #endif

        if(vidFmt == PCAM_USB_VIDEO_FORMAT_MJPEG){
            if((gbStopMJPEGEvent == 0) && (gbStopPreviewEvent == 0)){
            }
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422){
            if((gbStopYUV422Event == 0) && (gbStopPreviewEvent == 0)){
#if DRAM_SIZE <= 2
#ifndef ZDW_BARCODE
			//if(!bPowerOnWorking)
                MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE); //Ken
#endif
#endif
            }//if(m_VideoFmt
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_RAW){
        }
        else // H264
        {
#if DRAM_SIZE <= 2
            if(pipe0_cfg == PIPE_CFG_YUY2){
                MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE);
            }
#endif
        }
        if(UsbTransfer.bSrcPause == MMP_TRUE){
            MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE);
            UsbTransfer.bSrcPause = MMP_FALSE;
        }

        // bossino@2012_11_28, wait for the last packet is sent completed
        // otherwise the previous frame may be re-sent (for double buffer case)
        if(UsbTransfer.fb.phase == RT_TX_END){
            UsbTransfer.fb.phase = RT_TX_IDLE;
        }
        MMPF_USB_WaitDMA();
        if(glWaitDMA==0) {
        MMPF_USB_ReleaseDMA();
        }else{
            dbg_printf(3,"UVC Send Blk Not ReleaseDMA!!!\r\n");
        }

        UsbTransfer.toggle ^= 1;
        UvcSampleBuilder.nFrame++;
        dma_blk = MMPF_Video_GetCurBlk();
        if(dma_blk->next_blk == 0)
            UvcSampleBuilder.initialized = 0;
        else
            UvcSampleBuilder.initialized = 1;
        UsbTransfer.fb.bKeepSending = 0;
    }  // end of if(endbit == UVC_EOF)
    else{
        // if(endbit != UVC_EOF)
        MMP_BOOL waitIBCflag = 0;
        MMPF_IBC_PIPEID pipe = MMPF_IBC_PIPE_MAX;//assume MMPF_IBC_PIPEID is the same is stream CFG ID

        dma_blk = MMPF_Video_GetCurBlk();
        if((dma_blk->flag & (DMA_BLK_RING | DMA_BLK_SRC_IBC)) == (DMA_BLK_RING | DMA_BLK_SRC_IBC)){
            pipe = GET_DMA_BLK_PIPE(dma_blk->flag);
            if(!_uvc_tx_has_ibc_data(pipe)){
                waitIBCflag = 1;
            }
        }

        if(waitIBCflag == 0){
            dma_blk = MMPF_Video_GetCurBlk();
            if(UsbTransfer.tx_len == 0){
                app3_header = MMPF_Video_GetBlkAppHeader(dma_blk) ;
            }
            UsbTransfer.pNextPayload = (volatile MMP_UBYTE *)
                                       _uvc_prepare_next_transfer(dma_blk, sti_mode,
                                                                  app3_header,
                                                                  (MMP_ULONG *) &UsbTransfer.usb_dma_len);
            if(dma_blk->flag & DMA_BLK_RING){
                UsbTransfer.fb.ProcSize += UsbTransfer.usb_dma_len;
            }
            UsbTransfer.bWaitDMADone = 1;
        }
        else{
            UsbTransfer.bWaitDMADone = 0;
            UsbTransfer.pNextPayload = 0;
        }
    }
    return endbit;
}
#else
MMP_UBYTE usb_vc_send_blk(MMP_UBYTE sti_mode)
{
    STREAM_DMA_BLK *dma_blk ;
    volatile MMP_UBYTE *cur_pt = 0;
    MMP_UBYTE   endbit = 0;
    MMP_USHORT  xsize;
    MMP_UBYTE   *app3_header = 0;
    MMP_ULONG   send_size = 0;
    PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;
    MMP_UBYTE   pipe0_cfg,pipe1_cfg ;
    STREAM_CFG *stream_cfg = (STREAM_CFG *) usb_get_stream_cfg();

    pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);

#if SPEED_UP_PREVIEW_FRAME_RATE
    if(UvcSampleBuilder.initialized >= 1){
        dma_blk = MMPF_Video_GetCurBlk();

        // check if move DMA done.
        if(gbWaitDMADoneFlag == 1){
            cur_pt = (volatile MMP_UBYTE *) pNextPayload;
            if(cur_pt == 0){
                if(((dma_blk->flag & DMA_BLK_RING) == 0) &&
                   (dma_blk->next_blk != 0) &&
                   ((dma_blk->next_blk->flag & (DMA_BLK_RING | DMA_BLK_SRC_IBC)) == (DMA_BLK_RING | DMA_BLK_SRC_IBC))){
                    //first block of IBC ring
                    YuvPhase = 1;
                    glRingBufProcSize = 0;
                    MMPF_Video_UpdateRdPtrByPayloadLength(stream_cfg->pipe_en & PIPE_ASYNC);
                }
                if(!MMPF_Video_GoNextBlk()){
                    endbit = UVC_EOF;
                    cur_pt = (volatile MMP_UBYTE *) usb_vc_fill_empty_packet(dma_blk, endbit, sti_mode) ;
                    xsize = sizeof(UVC_VIDEO_PAYLOAD_HEADER);//12;
                    usb_preclose_Tx_flag = 1;
                }
                else{
                    if((dma_blk->flag & DMA_BLK_RING) && ((dma_blk->next_blk->flag & DMA_BLK_RING) == 0)){
                        if(YuvPhase == 2){
                            YuvPhase = 3;
                        }
                    }
                    xsize = glDMADoneSendSize ; // Force zero frame first
                    gbdrawflag = 1 ;
                    MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 4, (void *) NULL);
                }
            }
            else{
                if((dma_blk->flag & DUMMY_DMA_BLK) == 0){
                    // check if dummy block to skip Move DMA function
                    if(usb_vc_wait_dma_done(MMPF_DMA_R_0, 10000000) != MMP_ERR_NONE){
                        RTNA_DBG_Str3("Wait Dma Out 1\r\n");
                        while(1);
                    }
                }
                xsize = glDMADoneSendSize;
            }

            gbWaitDMADoneFlag = 0;
        }
        else{
            gbdrawflag = 1 ;
            //MMPF_OS_Sleep(1);//release the Task resoure to low priority task.
            MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 6, (void *) NULL);
        }
    }  // end of if(UvcSample.packet_count >= 1)
    else
    #endif
    {
        dma_blk = MMPF_Video_GetCurBlk();
#if STREAM_DMA_BLK_VER >= 2
        Transfer.cur_addr = dma_blk->blk_addr;
#endif

        app3_header = MMPF_Video_GetBlkAppHeader(dma_blk);
        cur_pt = (volatile MMP_UBYTE *) usb_vc_move_packet(dma_blk, endbit, sti_mode, app3_header, &send_size);
        if(cur_pt == 0){
            if(!MMPF_Video_GoNextBlk()){
                endbit = UVC_EOF;
                cur_pt = (volatile MMP_UBYTE *) usb_vc_fill_empty_packet(dma_blk, endbit, sti_mode) ;
                xsize = sizeof(UVC_VIDEO_PAYLOAD_HEADER);//12;
                usb_preclose_Tx_flag = 1;
            }
            else{
#if DBG_RING_BLK
                dbg_blk ++;
                dbg_printf(3, "<%d>", dbg_blk);
                if(Transfer.cur_addr == yuv_addr && (usbframecount < 3)){
                    dbg_printf(3, "%d", MMPF_IBC_GetRingBufWrPtr(MMPF_IBC_PIPE_0));
                }
#endif
                xsize = send_size; // Force zero frame first
                gbdrawflag = 1;
                //              MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_USBOP, MMPF_OS_FLAG_SET);
                MMPF_USBCTL_PostMsg(2, TASK_USB_PRIO, USBCTL_MSG_OTHERS, 5, (void *) NULL);
            }
        }
        else{
            if((dma_blk->flag & DUMMY_DMA_BLK) == 0){
                // check if dummy block to skip Move DMA function
                if(usb_vc_wait_dma_done(MMPF_DMA_R_0, 10000000) != MMP_ERR_NONE){
                    RTNA_DBG_Str3("Wait DMA Out 2\r\n");
                    while(1);
                }
            }
            xsize = send_size ;
        }
    }    

    if(cur_pt){
        usb_vc_send_packet((MMP_ULONG) cur_pt, xsize);
        UvcSampleBuilder.initialized++;
    }

    if(endbit == UVC_EOF){
        if(usbframecount == 20){
            ISP_IF_AE_SetFastMode(0); //do fastmode about 4 times AE calc.
            RTNA_DBG_Str3("Disable AE Fast Mode\r\n");
        }
#if DBG_RING_BLK
        if(usbframecount < 3){
            MMP_USHORT i;
            for(i = 0;i < UvcSampleBuilder.initialized;i++){
                if(i % 10 == 0){
                    dbg_printf(3, "\r\n[%d]", i);
                }
                dbg_printf(3, "%d ", dbg_tx_size[i]);
            }
        }
#endif
        if(vidFmt == PCAM_USB_VIDEO_FORMAT_MJPEG){
            if((gbStopMJPEGEvent == 0) && (gbStopPreviewEvent == 0)){
            }
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422){
            if((gbStopYUV422Event == 0) && (gbStopPreviewEvent == 0)){
#if DRAM_SIZE <= 2
                MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE);
#endif
            }//if(m_VideoFmt
        }
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_RAW){
        }
        else // H264
        {
#if DRAM_SIZE <= 2
            if(pipe0_cfg == PIPE_CFG_YUY2){
                MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE);
            }
#endif
        }
        DRB(dbg_blk = 0);
        MMPF_Timer_Log(&tlRd0E);

        if(Transfer.bSrcPause == MMP_TRUE){
            MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_0, MMP_TRUE);
            Transfer.bSrcPause = MMP_FALSE;
        }

        if(YuvPhase == 3){
            YuvPhase = 0;
        }        
        // bossino@2012_11_28, wait for the last packet is sent completed
        // otherwise the previous frame may be re-sent (for double buffer case)
        MMPF_USB_WaitDMA(); 
        MMPF_USB_ReleaseDMA();

        UvcSampleBuilder.toggle ^= 1;
        usbframecount++;
        UvcSampleBuilder.initialized = 0;
    }  // end of if(endbit == UVC_EOF)
#if SPEED_UP_PREVIEW_FRAME_RATE
    else{
        // if(endbit != UVC_EOF)
        MMP_BOOL waitIBCflag = 0;

#if DRAM_SIZE <= 2
        MMPF_IBC_PIPEID pipe = MMPF_IBC_PIPE_MAX;//assume MMPF_IBC_PIPEID is the same is stream CFG ID
        dma_blk = MMPF_Video_GetCurBlk();
        if((dma_blk->flag & (DMA_BLK_RING | DMA_BLK_SRC_IBC)) == (DMA_BLK_RING | DMA_BLK_SRC_IBC)){
            pipe = GET_DMA_BLK_PIPE(dma_blk->flag);
            if(!_uvc_tx_has_ibc_data(pipe)){
                waitIBCflag = 1;
            }
        }
#endif

        if(waitIBCflag == 0){
            dma_blk = MMPF_Video_GetCurBlk();
            app3_header = MMPF_Video_GetBlkAppHeader(dma_blk) ;
            pNextPayload = (volatile MMP_UBYTE *) usb_vc_move_packet(dma_blk, endbit, sti_mode, app3_header,
                                                                     &glDMADoneSendSize);
            if(dma_blk->flag & DMA_BLK_RING){
                glRingBufProcSize += glDMADoneSendSize;
            }
            gbWaitDMADoneFlag = 1;
        }
        else{
            gbWaitDMADoneFlag = 0;
            pNextPayload = 0;
        }
    }
#endif
    return endbit;
}
#endif//(STREAM_DMA_BLK_VER == 3)
void usb_vc_advance_to_lastframe(STREAM_CFG *stream_cfg, PIPE_PATH pipe)
{
    STREAM_CTL  *cur_bctl ;
    OS_CPU_SR   cpu_sr = 0;
    //
    // Always get the latest frame of YUY2 or MJPEG
    //
    // Lock IRQ when update the pointer
    IRQ_LOCK(cur_bctl = (pipe == PIPE_0) ? &PIPE_INFO(0, b) : &PIPE_INFO(1, b);
        if(cur_bctl->wr_index == 0) {
            cur_bctl->rd_index = (cur_bctl->slot_size * (cur_bctl->slot_num - 1)) ;
            cur_bctl->total_rd = cur_bctl->total_wr - 1;
        } else{
            cur_bctl->rd_index = cur_bctl->wr_index - cur_bctl->slot_size ;
            cur_bctl->total_rd = cur_bctl->total_wr - 1;
        })
}

/*
void usb_vc_advance_to_curframe(STREAM_CFG *cur_stream,MMP_UBYTE pipe)
{
    STREAM_CTL  *cur_bctl ;
    OS_CPU_SR   cpu_sr = 0;
    //
    // Always get the latest frame of YUY2 or MJPEG
    //
    // Lock IRQ when update the pointer
    IRQ_LOCK(
        if(pipe==0) {
            cur_bctl = &cur_stream->pipe0_b;
        }    
        else {
            cur_bctl = &cur_stream->pipe1_b;
        }

            cur_bctl->rd_index = cur_bctl->wr_index;
            cur_bctl->total_rd = cur_bctl->total_wr;
    )

}
*/

/**
 *  @brief Wait for data in the image pipe
 *  @param[in] pipe the number of pipe
 *  @retval 0 time out
 *  @retval 1 OK. The data is there as expected.
 */
MMP_UBYTE usb_vc_expect_pipe_data(const PIPE_PATH pipe)
{
    MMP_ULONG timeout;
    STREAM_CTL *cur_bctl;
    timeout = 0;
    while(MMPF_Video_IsEmpty(pipe)){
        timeout++;
        MMPF_OS_Sleep_MS(1);
        if(timeout > 2000){
            //consider open another parameter if the value other than 2000 is needed.
            cur_bctl = MMPF_Video_GetStreamCtlInfo(pipe);//&cur_pipe->pipe1_b;
            dbg_printf(2, "r/w:%d/%d pipe%d time out\r\n", cur_bctl->total_rd, cur_bctl->total_wr, pipe);
            return 0;
        }
    }
    return 1;
}



/** @brief Send the image to the host
 *
 *  The image here refers to UVC sample. A sample might be in frame-based, YUY2 or MJPEG sample container.
 *  A sample might consists of multiple image with different headers or tailings.
 *
 *  @param[in] sti_mode if this is still image.
 */
MMP_UBYTE usb_vc_send_image(MMP_UBYTE sti_mode)
{
#define MAX_APP3_LEN    ( 65532 ) // Let 0xFFE3 + Len Field(2Bytes) + 65531 = 65535 = 64KB

    volatile FRAME_PAYLOAD_HEADER *h264_1_ph, *h264_2_ph, *jpeg_ph;
    volatile MMP_ULONG h264_1_payload_size, h264_2_payload_size, jpeg_payload_size;
    volatile MMP_ULONG h264_addr1, h264_addr2, jpeg_addr;
 
#ifdef ZDW_BARCODE
#ifndef ZDW_BARCODE_POWER_ON_WORKING   
    volatile MMP_UBYTE* p;
#endif
#endif

    MMP_UBYTE   endbit = 0;
    
	//MMP_UBYTE* pBuff01;
	double dd;
	
    //volatile MMP_UBYTE *ptt;
#define ptt ((volatile MMP_UBYTE *) UvcSampleBuilder.stream_addr)

    PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;
    FRAME_PAYLOAD_HEADER *frame_ph ;
    STREAM_CFG *stream_cfg = (STREAM_CFG *) usb_get_stream_cfg();
    MMP_UBYTE   pipe0_cfg,pipe1_cfg,pipe2_cfg;
    PIPE_PATH pipe;

    pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);
    pipe2_cfg = GET_PIPE_FORMAT(stream_cfg, 2);

    if(m_bVidRecdPreviewStatus != 1){
        return UVC_SEND_IMG_RET_CONTINUE;
    }

		dd = sqrt(2);

    if(UvcSampleBuilder.initialized == 0){
#if (CAPTURE_BAYER_RAW_ENABLE == 0)
        // Wait all pipe 's frame are ready in the first frame.
        if(UvcSampleBuilder.nFrame == 0){
            if((gbCurH264Type != FRAMEBASE_DUAL_H264) && (gbCurH264Type != FRAMEBASE_DUAL_H264_MJPEG) && (gbCurH264Type != FRAMEBASE_H264FRAME_MJPEG)){
                if((stream_cfg->pipe_en & PIPE0_EN) && ((IS_PIPE_RING(stream_cfg, 0) == 0))){
                    if(!usb_vc_expect_pipe_data(PIPE_0)){
                        return UVC_SEND_IMG_RET_CONTINUE;
                    }
                }
                if((stream_cfg->pipe_en & PIPE1_EN) && ((IS_PIPE_RING(stream_cfg, 1) == 0))){
                    if(!usb_vc_expect_pipe_data(PIPE_1)){
                        return UVC_SEND_IMG_RET_CONTINUE;
                    }
                }
                if((stream_cfg->pipe_en & PIPE2_EN) && ((IS_PIPE_RING(stream_cfg, 2) == 0))){
                    if(!usb_vc_expect_pipe_data(PIPE_2)){
                        return UVC_SEND_IMG_RET_CONTINUE;
                    }
                }
            }
        }
#endif

        if((stream_cfg->pipe_en & PIPE_EN_MASK) == (PIPE0_EN | PIPE1_EN)){
            // Dual streams , get pipe 1
#if USB_MJPEGH264_STREAM || USB_FRAMEBASE_H264_MJPEG_STREAM
            if((gbCurH264Type == UVC_H264) || (FRAMEBASE_H264RT_MJPEG == gbCurH264Type)){
                // MJPEG + H.264

                if(pipe0_cfg == PIPE_CFG_MJPEG)
                    pipe = PIPE_0 ;
                else
                    pipe = PIPE_1 ;

                usb_vc_advance_to_lastframe(stream_cfg, pipe) ;

                //find MJPEG
                UvcSampleBuilder.stream_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(pipe) ;
            }
            else
#endif
            {
                // YUY2 + H.264
                //find H.264
                if(pipe0_cfg == PIPE_CFG_H264){
                    UvcSampleBuilder.stream_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_0) ; // PIPE 0 :H264
                    //dbg_printf(3, "addr = x%X\r\n", UvcSampleBuilder.stream_addr);
                }
                else
                    UvcSampleBuilder.stream_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_1) ; // PIPE 1 :H264
            }
        }
        else{
            // Single Stream

            if((pipe0_cfg == PIPE_CFG_MJPEG) || (pipe0_cfg == PIPE_CFG_YUY2) || (pipe0_cfg == PIPE_CFG_H264))
                pipe = PIPE_0 ;
            else if(pipe1_cfg == PIPE_CFG_H264)
                pipe = PIPE_1;  // H.264 only
            else if((pipe2_cfg == PIPE_CFG_YUY2) || (pipe2_cfg == PIPE_CFG_MJPEG))
                pipe = PIPE_2;

            if((vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422) || (vidFmt == PCAM_USB_VIDEO_FORMAT_RAW)){
                if(IS_PIPE_RING(stream_cfg, pipe) == 0){
                    //Do this only when it is plain buffer
                    usb_vc_advance_to_lastframe(stream_cfg, pipe) ;
                }
            }

            //Find the only stream
            UvcSampleBuilder.stream_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(pipe) ;
        }

        if(UvcSampleBuilder.stream_addr == 0){
            RTNA_DBG_Str3("Strange usb_local_address\r\n");
            UvcSampleBuilder.stream_addr = glPCCAM_VIDEO_BUF_ADDR ;
        }
        else{
            //usb_check_reframe--;
        }
        usb_close_Tx_flag = 0;
        usb_preclose_Tx_flag = 0;
        //}

        //ptt = (volatile MMP_UBYTE *) UvcSampleBuilder.usb_local_address;

        //if(UvcSampleBuilder.initialized == 0) {  //first package of frame

        UsbTransfer.PTS = PTS;
        //Skype_PTS = (MMP_ULONG)(MMPF_3GPMGR_GetTimeCounter() * glCPUFreq);
#if (SECS_VER > 0)
        Skype_PTS_L = (MMP_ULONG) (MMPF_VIDMGR_GetTimeCounter() * 90);
        if(Skype_PTS_L > (0xffffffff - 450000)){
            Skype_PTS_L = 0;
            Skype_PTS_H++;
        }
#endif
		#if (USB_UVC_BULK_EP)
        MMPF_Video_InitDMABlk((TX_PER_FRAME * HS_TX_MAX_PK_SIZE - 12), glUSB_UVC_DMA_BUF_ADDR1, glUSB_UVC_DMA_BUF_ADDR2);
        _uvc_tx_init((TX_PER_FRAME * HS_TX_MAX_PK_SIZE - 12), glUSB_UVC_DMA_BUF_ADDR1, glUSB_UVC_DMA_BUF_ADDR2);
        #else
        MMPF_Video_InitDMABlk((UVCTxFIFOSize - 12), glUSB_UVC_DMA_BUF_ADDR1, glUSB_UVC_DMA_BUF_ADDR2);
        _uvc_tx_init((UVCTxFIFOSize - 12), glUSB_UVC_DMA_BUF_ADDR1, glUSB_UVC_DMA_BUF_ADDR2);
        #endif

        frame_ph = (FRAME_PAYLOAD_HEADER *) ptt;

        if(vidFmt == PCAM_USB_VIDEO_FORMAT_MJPEG){
#if (CAPTURE_BAYER_RAW_ENABLE == 1)

            UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;

#else
            if(frame_ph->Common.dwPayloadSize < glPCCamCompressBufSize)
                UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;
            else
                UvcSampleBuilder.main_size = 0;

    #if XU_FRAMEBASE_CAPTURE
            if(gFramebaseCap.format != CF_MJPEG/*2*/)
    #endif
                if((frame_ph->FRAME_H264_PH.wImageHeight % 8) != 0){
                    // Re-adjust JPEG height if the input height is not multiple of 8
                    usb_uvc_align_jpeg_height((MMP_UBYTE *) (ptt + FRAME_PAYLOAD_HEADER_SZ),
                                              UvcSampleBuilder.main_size, frame_ph->FRAME_H264_PH.wImageHeight);
                }
#endif

#if SUPPORT_METHOD_1_MJPEG_CAPTURE_EXIF && (CUSTOMER == ASU)
#if 0 //keep for debug log
        {
            unsigned short iAddrOffset;
            dbg_printf(0, "[!2] glFrameLength=%d,\r\n", UvcSampleBuilder.main_size);
            for(iAddrOffset=0; iAddrOffset<64; iAddrOffset++) {
                dbg_printf(0, " %02X  ", (MMP_UBYTE)*(MMP_UBYTE*)(ptt + FRAME_PAYLOAD_HEADER_SZ + iAddrOffset));
            }
        }
#endif
            //ISP_IF_AE_GetExifShutter(); //TBD
            //ISP_IF_AE_GetExifISO(); //TBD
            if(UvcSampleBuilder.main_size){
                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 2, 0);
                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ExifEncodeData), 0xB9, 0);
                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ + 2),
                                     UvcSampleBuilder.main_size - 2, 0);
            }
            else 
#endif
            {
#if XU_FRAMEBASE_CAPTURE
                if(gFramebaseCap.JPEG && (!gFramebaseCap.SECS)){
                    if(frame_ph->FRAME_H264_PH.wStreamType == ST_CaptureJPG)
                        dbg_printf(3, "## FB_MJPG Capture Mode ##\r\n");
                }
                if(UvcSampleBuilder.main_size == 0){
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
                }
                else if(gFramebaseCap.SECS){
                    *(MMP_ULONG *) (ptt + UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ) = 0x47504A4D;//Capture SECS tag = "MJPG"
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ),
                                         UvcSampleBuilder.main_size + 4, 0);
                    dbg_printf(3, "## SECS_MJPG Capture Mode ##\r\n");
                }
                else if(gFramebaseCap.format == CF_MJPEG/*2*/){
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ, 0);
                }
        #if BIND_SENSOR_AR0832E
                else if(gFramebaseCap.JPEG){
                    gFramebaseCap.JPEG = 0;
                    PH_SET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag, 2);
                    MMPF_Video_AddDMABlk(0,(MMP_ULONG)(ptt), UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ ,0);
                }
        #endif
                else
#endif
                if(PH_GET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag) == 1){
                    PH_SET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag, 2);
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), UvcSampleBuilder.main_size, 0);
                }
            }
        }
        else if((vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422) || (vidFmt == MMPS_3GPRECD_VIDEO_FORMAT_YUV420)){
#if DRAM_SIZE <= 2
            MMP_ULONG max_ring_buf_size;
            STREAM_CTL *cur_bctl;
            
            cur_bctl = &(PIPE_INFO(pipe, b));
            
            max_ring_buf_size = cur_bctl->slot_size - FRAME_PAYLOAD_HEADER_SZ;
            UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize;
            if(UvcSampleBuilder.main_size == 0){
                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
            }
            else if(IS_PIPE_RING(stream_cfg, pipe)){
                MMP_LONG tx_len, left_len;
#if XU_FRAMEBASE_CAPTURE
                if(gFramebaseCap.format == CF_YUY2/*1*/){
                    left_len = UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ;
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), FRAME_PAYLOAD_HEADER_SZ, 0);
                }
                else
#endif
                {
                    left_len = UvcSampleBuilder.main_size ;
                }
                do{
                    tx_len = VR_MIN(left_len, max_ring_buf_size);
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), tx_len,
                                         PIPE0_RING | DMA_BLK_SRC_IBC);
                    left_len -= tx_len;
                    MMPF_IBC_SetStoreEnable(pipe, MMP_FALSE);
                    UsbTransfer.bSrcPause = MMP_TRUE;
#if (DRAW_TEXT_FEATURE_EN==ON)
                    gTextColorFormat = ISP_PREVIEW_FORMAT_YUV422;
                    gTextPreviewWidth = PIPE_INFO(pipe, w) ;
                    gTextPreviewBufAddr = (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ);
                    // print string on preview frames
                    VR_PrintStringOnPreview();
#endif
                }
                while(left_len > 0);
            }
            else 
#endif
            {
                //not ring
                if(frame_ph->Common.dwPayloadSize < glPCCAM_VIDEO_BUF_MAX_SIZE)
                    UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;
                else
                    UvcSampleBuilder.main_size = 0;

#if XU_FRAMEBASE_CAPTURE
                if(gFramebaseCap.format == CF_YUY2/*1*/){
                    MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ, 0);
                }
                else
                #endif
                {
                    if(PH_GET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag) == 1){
                        PH_SET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag, 2);
                       
                       /*
                       //Allocate buffers
                        pBuff01 = MMPF_SYS_AllocFB("YUY2",307200,8);
						   //MMPF_SetPCCAMCompressBuf(pBuff01,307200);    
						PCAM_USB_ResetSlotBuf(0, 1, pBuff01, 307200);
                		*/
               		
#ifdef ZDW_BARCODE
#ifndef ZDW_BARCODE_POWER_ON_WORKING 
						//if((bTriggering == MMP_TRUE)&&(ExposureAdj() == MMP_TRUE))
						p= ptt + FRAME_PAYLOAD_HEADER_SZ;
						KK_BarcodeScanning(p);
#endif
#endif	
						MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), UvcSampleBuilder.main_size, 0);
                    }
                }
            }

#if (DRAW_TEXT_FEATURE_EN==ON)
            if(vidFmt == PCAM_USB_VIDEO_FORMAT_YUV422){
                gTextColorFormat = ISP_PREVIEW_FORMAT_YUV422;
                gTextPreviewWidth = PIPE_INFO(0, w) ;

                gTextPreviewBufAddr = (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ);
                // print string on preview frames
                VR_PrintStringOnPreview();
            }    
#endif
        } 
#if CAPTURE_BAYER_RAW_ENABLE
        else if(vidFmt == PCAM_USB_VIDEO_FORMAT_RAW){
            UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;
#if 1
            RTNA_DBG_Str3("Raw.Frame.Len:");
            RTNA_DBG_Long3(UvcSampleBuilder.main_size);
            RTNA_DBG_Str3("\r\n");
#endif

            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), UvcSampleBuilder.main_size, 0);
        } 
#endif
        else{
            // includes any H.264

#if USB_FRAMEBASE_H264_ONLY
            MMP_UBYTE framebase_h264 = 0 ;
            // H264 stream:
            // 1. Pure Frame base stream
            // 2. Skype Mode B
            // 3. LGT H264 + MJPG
            // single pipe , treat it as Framebase H264
            if(((stream_cfg->pipe_en & PIPE0_EN) == 0) || (gbCurH264Type == FRAMEBASE_H264)){
                //RTNA_DBG_Str3("FrameBase.H264\r\n");
                framebase_h264 = 1;
            }
#endif
            UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;
            
            switch(gbCurH264Type){
#if USB_FRAMEBASE_H264_ONLY
            case FRAMEBASE_H264:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->FRAME_H264_PH.dwPayloadSize ;
                if(framebase_h264){
                    if((UvcSampleBuilder.nFrame == 0) || (UvcSampleBuilder.main_size == 0)){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        if(PH_GET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag) == 1){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt),
                                                 UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ, 0);
                            PH_SET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag, 2);
                        }
                    }
                }
                break ;
#endif
#if SKYPE_MODE_B//USB_UVC_SKYPE
            case SKYPE_H264:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->SKYPE_H264_PH.dwPayloadSize ;
                #if 0
                RTNA_DBG_Str3("  glFrameLength : ");
                RTNA_DBG_Long3(UvcSampleBuilder.main_size );
                RTNA_DBG_Str3("\r\n");
                #endif

                if(gbSkypeMode == 0x02){
                    FRAME_PAYLOAD_HEADER *yuv_ph ;
                    MMP_ULONG yuy2_addr ;

                    if(pipe0_cfg == PIPE_CFG_YUY2)
                        pipe = PIPE_0 ;
                    else
                        pipe = PIPE_1 ;

                    usb_vc_advance_to_lastframe(stream_cfg, pipe) ;
                    yuy2_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(pipe) ;  // YUY2
                    yuv_ph = (FRAME_PAYLOAD_HEADER *) yuy2_addr ;

                    // Force to send dummy frame
                    if(usbframecount == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        if(yuv_ph->UVC_H264_PH.dwPayloadSize > 640 * 480){
                            RTNA_DBG_Str3("H264 Size Crash> 640*480\r\n");
                        }

                        if(/*yuv_ph->UVC_H264_PH.dwPayloadSize &&*/UvcSampleBuilder.main_size){
                            MMP_ULONG h264_payload_size;

                            h264_payload_size = UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ;
                            // H264. valid frame 
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), h264_payload_size, 0);
                            // H264. dummy frame 
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + h264_payload_size),
                                                 (640 * 480 - h264_payload_size), 1);

                            // YUY2 valid frame = 384*216*2
                            yuv_preview_size = 384 * 216 * 2;
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr + FRAME_PAYLOAD_HEADER_SZ),
                                                 yuv_preview_size, 0);

                            // YUY2 dummy frame = 640*480 - 384*216*2
                            MMPF_Video_AddDMABlk(0,
                                                 (MMP_ULONG) (yuy2_addr + FRAME_PAYLOAD_HEADER_SZ + yuv_preview_size),
                                                 (640 * 480 - yuv_preview_size), 1);
                        }
                        else{
                            //if((yuv_ph->UVC_H264_PH.dwPayloadSize)&&(!UvcSample.main_size)){
                            RTNA_DBG_Str3("Lost H264 Frame\r\n");
                            //}
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
                            //RTNA_DBG_Str3("Empty Frame\r\n");
                        }
                    }
                }
                break;   
#endif  
#if USB_FRAMEBASE_H264_MJPEG_STREAM
                // for now one MJPEG frame is always with H.264 frame
            case FRAMEBASE_H264RT_MJPEG:
                //MJPEG
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize;
                 {
                    MMP_UBYTE *jpeg_ptr, *h264_ptr;
                    FRAME_PAYLOAD_HEADER *h264_ph;
                    jpeg_ptr = ((MMP_UBYTE *) frame_ph);

                    if(pipe0_cfg == PIPE_CFG_H264)
                        h264_ptr = MMPF_Video_CurRdPtr(0);
                    else
                        h264_ptr = MMPF_Video_CurRdPtr(1);

                    h264_ph = (FRAME_PAYLOAD_HEADER *) h264_ptr;

                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_ptr), 0, 0);
                    }
                    else{
                        if((h264_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(h264_ph->FRAME_H264_PH.dwFlag) == 1)){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) h264_ptr,
                                                 h264_ph->Common.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ, 0);
                            PH_SET_TX_CTL(h264_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(1, bDirty) = MMP_TRUE;
                        }
                        if((frame_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag) == 1)){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) jpeg_ptr,
                                                 UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ, 0);
                            PH_SET_TX_CTL(frame_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(0, bDirty) = MMP_TRUE;
                        }
                    }
                }
                break;
            case FRAMEBASE_H264FRAME_MJPEG:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->FRAME_H264_PH.dwPayloadSize ;
                {
                    MMP_USHORT send_count = 0;
#pragma O0
#if Y_DATA_EN || RAW_DATA_EN
                    volatile FRAME_PAYLOAD_HEADER *y_ph;
                    volatile MMP_ULONG  y_addr;
    #if SUPPORT_AIT845x_MD
                    extern MMP_BOOL send_md_flag;
                    extern MMP_UBYTE md_num;
                    volatile FRAME_PAYLOAD_HEADER *md_ph;
                    volatile MMP_ULONG md_addr;
                    md_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_M);
                    md_ph = (FRAME_PAYLOAD_HEADER *) md_addr;
    #endif
    #if SUPPORT_PIPE_Y  //RAW to Y
                    y_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_Y);
    #else
                    y_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_G);
    #endif
                    y_ph = (FRAME_PAYLOAD_HEADER *) y_addr;
#endif

                    h264_addr1 = (MMP_ULONG) MMPF_Video_CurRdPtr(0);  // PIPE 0
                    jpeg_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(2);  // PIPE 2

                    h264_1_ph = (volatile FRAME_PAYLOAD_HEADER *) h264_addr1;
                    jpeg_ph = (volatile FRAME_PAYLOAD_HEADER *) jpeg_addr;

#if (SUPPORT_H264MV_MD)
                    MMPF_VIDENC_GetParameter(1, MMPF_VIDENC_ATTRIBUTE_FILTER_MODE, (void*)&FilterMode);
                    h264_mv_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(1);
                    h264_mv_ph = (FRAME_PAYLOAD_HEADER *)h264_mv_addr;
#endif
                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        // 1st H264. valid frame
                        if((h264_1_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag) == 1)){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_1_ph), h264_1_ph->FRAME_H264_PH.dwPayloadSize + 32, 0x10);
                            PH_SET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(0, bDirty) = MMP_TRUE;
                            send_count++;
                    #if 0
                            dbg_printf(3,"0x%x H0(%d):0x%X, 0x%X\r\n",(MMP_ULONG) h264_1_ph, h264_1_ph->FRAME_H264_PH.dwFrameSeq, glH264Size, h264_1_ph->FRAME_H264_PH.dwPayloadSize+32 );
                    #endif
                        }

                        // 3st MJPG. valid frame
                        if((jpeg_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(jpeg_ph->FRAME_H264_PH.dwFlag) == 1)){
                            //*********************************************
                            //Addr + Header(32) + QTable(206) = MJPEG_H
                            //Addr + Header(32) + QTable(208) = MJPEG_W
                            //if(*(MMP_USHORT*)(jpeg_addr+0xF0) == 0x4001)
                            //    *(MMP_USHORT*)(jpeg_addr+0xF0) = 0x4001;
                            //if(*(MMP_USHORT*)(jpeg_addr+0xF0) == 0xA000))
                            //    *(MMP_USHORT*)(jpeg_addr+0xF0) = 0xA000;
                            if(*(MMP_USHORT*)(jpeg_addr+0xEE) == 0xB800)
                                *(MMP_USHORT*)(jpeg_addr+0xEE) = 0xB400;
                            if(*(MMP_USHORT*)(jpeg_addr+0xEE) == 0x6000)
                                *(MMP_USHORT*)(jpeg_addr+0xEE) = 0x5A00;
                            //*********************************************
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_ph), jpeg_ph->FRAME_H264_PH.dwPayloadSize + 32, 1);
                            PH_SET_TX_CTL(jpeg_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(2, bDirty) = MMP_TRUE;
                            send_count++;
                    #if 0
                            dbg_printf(3,"0x%x MJ(%d):0x%X\r\n", jpeg_addr, jpeg_ph->FRAME_H264_PH.dwFrameSeq, jpeg_ph->FRAME_H264_PH.dwPayloadSize);
                    #endif
                        }

#if Y_DATA_EN || RAW_DATA_EN
                        // 4st Y/RAW. valid frame
                        if((y_ph->FRAME_H264_PH.dwFrameSize) && (PH_GET_TX_CTL(y_ph->FRAME_H264_PH.dwFlag) == 1)){
                            //if((y_ph->FRAME_H264_PH.dwFrameSeq%3) ==0){// 3 frame only output 1 frame for USB bandwidth issue.
                                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (y_ph), y_ph->FRAME_H264_PH.dwPayloadSize + 32, 0);
                            //}
                            PH_SET_TX_CTL(y_ph->FRAME_H264_PH.dwFlag, 2);
    #if SUPPORT_PIPE_Y
                            PIPE_INFO(PIPE_Y, bDirty) = MMP_TRUE;
    #else
                            PIPE_INFO(PIPE_G, bDirty) = MMP_TRUE;
    #endif
                            #if 0
                            dbg_printf(3,"Y(%d)\r\n", y_ph->FRAME_H264_PH.dwFrameSize);
                            #endif
                            send_count++;
                        }
    #if SUPPORT_AIT845x_MD
                        if(send_md_flag&&md_num) {
                            md_ph->FRAME_H264_PH.wVersion = 0x0090;
                            md_ph->FRAME_H264_PH.wImageOffset = UVC_H264_PH_LEN;
                            md_ph->FRAME_H264_PH.wStreamType = ST_H264_MV;//ST_AIT845x_MD;
                            md_ph->FRAME_H264_PH.dwFlag = 0x8000;

                            md_ph->FRAME_H264_PH.wImageWidth = 0;
                            md_ph->FRAME_H264_PH.wImageHeight = 0;
                            md_ph->FRAME_H264_PH.wFrameRate = 0;
                            md_ph->FRAME_H264_PH.dwFrameSeq = 0;
                            md_ph->FRAME_H264_PH.dwTimeStamp = 0;
                            md_ph->FRAME_H264_PH.dwFrameSize = md_num;
                            md_ph->FRAME_H264_PH.dwPayloadSize = ALIGN32(md_num);
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG)md_ph, ALIGN32(md_num) + 32, 0);
                            send_md_flag = 0;
                            dbg_printf(3,"Send MD(%d)\r\n", md_num);
                            send_count++;
                        }
    #endif
#endif
#if (SUPPORT_H264MV_MD)
                        if (FilterMode != MMPF_VIDENC_FILTER_ENCODER){
                            // 2nd H264 MV frame
                            if((h264_mv_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(h264_mv_ph->FRAME_H264_PH.dwFlag) == 1)){
                                h264_mv_payload_size = h264_mv_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_mv_ph), h264_mv_payload_size, 0);
                                PH_SET_TX_CTL(h264_mv_ph->FRAME_H264_PH.dwFlag, 2);
                                PIPE_INFO(1, bDirty) = MMP_TRUE;
                        #if 0
                                dbg_printf(3,"H1(%d)\r\n", h264_mv_payload_size);
                        #endif
                                send_count++;
                                if(MD_Execute(PH_GET_STREAM_TYPE(h264_mv_ph->FRAME_H264_PH.dwFlag) & H264_UVC_PH_FLAG_IDR) == MOTION_DETECT) {
                                    PH_SET_STREAM_TYPE(h264_mv_ph->FRAME_H264_PH.dwFlag, (PH_GET_STREAM_TYPE(h264_mv_ph->FRAME_H264_PH.dwFlag) | H264_UVC_PH_FLAG_MD_TRG));
                                    dbg_printf(3, "** MD ** ");
                                }
                            }
                        }
#endif
                        if(send_count == 0){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                            RTNA_DBG_Str3("send count 0\r\n");
                        }
#pragma 
#if (SUPPORT_MP4) || (SUPPORT_MTS)
                        if(MMPF_VIDMGR_GetMtsMuxModeEnable() || MMPF_VIDMGR_GetMP4Enable())
                        {
                            MMP_ULONG aud_addr, audio_payload_size;                        
                            FRAME_PAYLOAD_HEADER *aud_ph;

                            if(!MMPF_Video_IsEmpty(PIPE_AUD))
                            {
                                aud_addr = (MMP_ULONG)MMPF_Video_CurRdPtr(PIPE_AUD);
                                aud_ph = (FRAME_PAYLOAD_HEADER *) aud_addr ;
                                audio_payload_size = aud_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;

                                if(PH_GET_TX_CTL(aud_ph->FRAME_H264_PH.dwFlag) == 1){
                                    PH_SET_TX_CTL(aud_ph->FRAME_H264_PH.dwFlag, 2);
                                    MMPF_Video_AddDMABlk(0, aud_addr, audio_payload_size, 0);
                            #if 0
                                    dbg_printf(3,"H3(%d)\r\n", audio_payload_size);
                            #endif
                                }
                            }
                        }
#endif
                    }
                }
                break;   
#endif
#if USB_MJPEGH264_STREAM //LGT mode
            case UVC_H264:
                // First Part Length is MJPEG.
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->UVC_H264_PH.dwPayloadSize ;
                #if 0
                if( MMPF_Video_IsEmpty( 0 ) ) {
                    RTNA_DBG_Str3("E0:");
                    RTNA_DBG_Long3(glFrameLength);
                    RTNA_DBG_Str3("\r\n");
                }
                RTNA_DBG_Str3("MJPEG.Frame.Len:");
                RTNA_DBG_Long3(glFrameLength );
                RTNA_DBG_Str3("\r\n");
                #endif
                 {
                    MMP_UBYTE *jpeg_ptr, *jpeg_payload_ptr, *h264_ptr , *h264_payload_ptr ;
                    MMP_ULONG app3_insert_addr = 0;
                    FRAME_PAYLOAD_HEADER *h264_ph;

                    if(pipe0_cfg == PIPE_CFG_H264)
                        h264_ptr = MMPF_Video_CurRdPtr(0) ;
                    else
                        h264_ptr = MMPF_Video_CurRdPtr(1) ;

                    h264_ph = (FRAME_PAYLOAD_HEADER *) (h264_ptr);

                    jpeg_ptr = (MMP_UBYTE *) frame_ph ;
                    jpeg_payload_ptr = (jpeg_ptr + FRAME_PAYLOAD_HEADER_SZ);

                    // Force 1st frame is Zero frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr), 0, 0);
                    }
                    else{
                        if(UvcSampleBuilder.main_size && h264_ph->UVC_H264_PH.dwPayloadSize){
                            MMP_ULONG off , *h264_ptr32;
                            app3_insert_addr = (MMP_ULONG) usb_uvc_search_app3_insert_addr((MMP_UBYTE *)
                                                                                           (jpeg_payload_ptr),
                                                                                           UvcSampleBuilder.main_size,
                                                                                           0xFFDD);
                            off = app3_insert_addr - (MMP_ULONG) jpeg_payload_ptr ;

                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr), off, 0);
#if 0
                           if( MMPF_Video_IsEmpty( 1 ) ) {
                               RTNA_DBG_Str3("E1:");
                               RTNA_DBG_Long3(h264_ph->UVC_H264_PH.dwPayloadSize);
                               RTNA_DBG_Str3("\r\n");
                           }
#endif

                            if(h264_ph->UVC_H264_PH.dwPayloadSize){
                                MMP_ULONG h264_blk_size = h264_ph->UVC_H264_PH.dwPayloadSize ;
                                MMP_ULONG tx_len , cur_addr,h264_off = 0;
                                if(h264_ph->UVC_H264_PH.dwPayloadSize > 64 * 1024){
                                    RTNA_DBG_Str3("H264.Len:");
                                    RTNA_DBG_Long3(h264_ph->UVC_H264_PH.dwPayloadSize);
                                    RTNA_DBG_Str3("\r\n");
                                }
                                h264_payload_ptr = h264_ptr + FRAME_PAYLOAD_HEADER_SZ ;
                                cur_addr = (MMP_ULONG) h264_ptr;//h264_payload_ptr ;
                                h264_ptr32 = (MMP_ULONG *) (h264_payload_ptr);

                                h264_blk_size = (h264_blk_size + 31) & (-32) ;

                                h264_blk_size += FRAME_PAYLOAD_HEADER_SZ ;

                                do{
                                    tx_len = (h264_blk_size > MAX_APP3_LEN) ? MAX_APP3_LEN : h264_blk_size ;
                                    MMPF_Video_AddDMABlk(DMA_BLK_JPEG_HDR_LEN, (MMP_ULONG) (cur_addr + h264_off),
                                                         tx_len, 0);
                                    h264_off += tx_len ;
                                    h264_blk_size -= tx_len ;
                                }
                                while(h264_blk_size) ;
                            }

                            UvcSampleBuilder.main_size = (UvcSampleBuilder.main_size + 31) & (-32) ;

                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr + off),
                                                 UvcSampleBuilder.main_size - off, 0);
                        }
                        else{
                            // Zero length frame or H264 length = 0
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr), UvcSampleBuilder.main_size, 0);
                        }
                    }
                }  
                break;                                     
#endif                  

#if USB_FRAMEBASE_H264_YUY2_STREAM
            case FRAMEBASE_H264_YUY2:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->FRAME_H264_PH.dwPayloadSize ;
                #if 0
                RTNA_DBG_Str3("  glFrameLength : ");
                RTNA_DBG_Long3(UvcSampleBuilder.main_size );
                RTNA_DBG_Str3("\r\n");
                #endif
                 {
                    FRAME_PAYLOAD_HEADER *yuv_ph2;
                    MMP_ULONG yuy2_addr2 ;

                    if(pipe0_cfg == PIPE_CFG_YUY2)
                        pipe = PIPE_0 ;
                    else
                        pipe = PIPE_1 ;

                    usb_vc_advance_to_lastframe(stream_cfg, pipe) ;
                    yuy2_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(pipe) ;  // YUY2
                    yuv_ph2 = (FRAME_PAYLOAD_HEADER *) yuy2_addr2 ;

                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        if(UvcSampleBuilder.main_size){
                            MMP_ULONG h264_payload_size2;

                            #if 0
                            RTNA_DBG_Str3("  glFrameLength : ");
                            RTNA_DBG_Long3(UvcSampleBuilder.main_size );
                            RTNA_DBG_Str3("\r\n");
                            #endif

                            h264_payload_size2 = UvcSampleBuilder.main_size + FRAME_PAYLOAD_HEADER_SZ;
                            // H264. valid frame
#if 1   
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), h264_payload_size2, 0);
#else  // only for test
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ),
                                                 UvcSampleBuilder.main_size, 0);
#endif

                            yuv_preview_size = ALIGN32(PIPE_INFO(0, w) * PIPE_INFO(0, h) * 2) +
                                               FRAME_PAYLOAD_HEADER_SZ;
                    #if 0
                            RTNA_DBG_Str(0, "  ** YUY2 wWidth = ");       
                            MMPF_DBG_Int(stream_cfg->pipe0_w, -4);
                            RTNA_DBG_Str(0, " : ");
                            RTNA_DBG_Str(0, "  wHeight = ");       
                            MMPF_DBG_Int(stream_cfg->pipe0_h, -4);
                            RTNA_DBG_Str(0, "\r\n");
                    #endif

                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr2), yuv_preview_size, 0);
                        }
                        else{
                            //if((yuv_ph2->UVC_H264_PH.dwPayloadSize)&&(!UvcSample.main_size)){
                            RTNA_DBG_Str3("Lost H264 Frame\r\n");
                            //}
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
                        }
                    }
                }
                break;   
#endif                    

#if USB_FRAMEBASE_DUAL_H264_STREAM
            case FRAMEBASE_DUAL_H264:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->FRAME_H264_PH.dwPayloadSize ;
                 {
                    FRAME_PAYLOAD_HEADER *h264_1_ph, *h264_2_ph;
                    MMP_ULONG h264_1_payload_size, h264_2_payload_size;
                    MMP_ULONG h264_addr1, h264_addr2;

                    h264_addr1 = (MMP_ULONG) MMPF_Video_CurRdPtr(0);
                    h264_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(1);

                    h264_1_ph = (FRAME_PAYLOAD_HEADER *) h264_addr1;
                    h264_2_ph = (FRAME_PAYLOAD_HEADER *) h264_addr2;

                    h264_1_payload_size = h264_1_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                    h264_2_payload_size = h264_2_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;

                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        // 1st H264. valid frame
                        if((h264_1_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag) == 1)){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_1_ph), h264_1_payload_size, 0);
                            PH_SET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(0, bDirty) = MMP_TRUE;
                    #if 0
                            dbg_printf(3,"H0(%d)\r\n", h264_1_payload_size);
                    #endif
                        }                            
                        // 2st H264. valid frame
                        if((h264_2_ph->FRAME_H264_PH.dwPayloadSize) && (PH_GET_TX_CTL(h264_2_ph->FRAME_H264_PH.dwFlag) == 1)){
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_2_ph), h264_2_payload_size, 0);
                            PH_SET_TX_CTL(h264_2_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(1, bDirty) = MMP_TRUE;
                    #if 0
                            dbg_printf(3,"H1(%d)\r\n", h264_2_payload_size);
                    #endif
                        }
                    }
                }
                break;   
            case FRAMEBASE_DUAL_H264_MJPEG:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->FRAME_H264_PH.dwPayloadSize ;
                 {
                    MMP_USHORT send_count = 0;
                    #if Y_DATA_EN || RAW_DATA_EN
                    FRAME_PAYLOAD_HEADER *y_ph;
                    MMP_ULONG y_payload_size, y_addr;
                    #if SUPPORT_AIT845x_MD
                    extern MMP_BOOL send_md_flag;
                    extern MMP_UBYTE md_num;
                    FRAME_PAYLOAD_HEADER *md_ph;
                    MMP_ULONG md_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_M);
                    md_ph = (FRAME_PAYLOAD_HEADER *) md_addr;
                    #endif
                    #endif

                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        h264_addr1 = (MMP_ULONG) MMPF_Video_CurRdPtr(0);
                        h264_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(1);
                        jpeg_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(2);

                        h264_1_ph = (FRAME_PAYLOAD_HEADER *) h264_addr1;
                        h264_2_ph = (FRAME_PAYLOAD_HEADER *) h264_addr2;
                        jpeg_ph = (FRAME_PAYLOAD_HEADER *) jpeg_addr;
                        
                        #if Y_DATA_EN || RAW_DATA_EN
                        #if SUPPORT_PIPE_Y  //RAW to Y
                        y_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_Y);
                        #else
                        y_addr = (MMP_ULONG) MMPF_Video_CurRdPtr(PIPE_G);
                        #endif
                        y_ph = (FRAME_PAYLOAD_HEADER *) y_addr;
                        #endif

                        // 1st H264. valid frame
                        if((h264_1_ph->FRAME_H264_PH.dwFrameSize) && (PH_GET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag) == 1)){
                            h264_1_payload_size = h264_1_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_1_ph), h264_1_payload_size, 0);
                            PH_SET_TX_CTL(h264_1_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(0, bDirty) = MMP_TRUE;
                            #if 0
                            dbg_printf(3,"H0(%d)\r\n", h264_1_payload_size);
                            #endif
                            send_count++;
                        }                            
                        // 2st H264. valid frame
                        if((h264_2_ph->FRAME_H264_PH.dwFrameSize) && (PH_GET_TX_CTL(h264_2_ph->FRAME_H264_PH.dwFlag) == 1)){
                            h264_2_payload_size = h264_2_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (h264_2_ph), h264_2_payload_size, 0);
                            PH_SET_TX_CTL(h264_2_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(1, bDirty) = MMP_TRUE;
                            #if 0
                            dbg_printf(3,"H1(%d)\r\n", h264_2_payload_size/*h264_2_ph->FRAME_H264_PH.dwFrameSize*/);
                            #endif
                            send_count++;
                        }
                        // 3st MJPG. valid frame
                        if((jpeg_ph->FRAME_H264_PH.dwFrameSize) && (PH_GET_TX_CTL(jpeg_ph->FRAME_H264_PH.dwFlag) == 1)){
                            jpeg_payload_size = jpeg_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                            //*********************************************
                            //Addr + Header(32) + QTable(206) = MJPEG_H
                            //Addr + Header(32) + QTable(208) = MJPEG_W
                            //if(*(MMP_USHORT*)(jpeg_addr+0xF0) == 0x4001)
                            //    *(MMP_USHORT*)(jpeg_addr+0xF0) = 0x4001;
                            //if(*(MMP_USHORT*)(jpeg_addr+0xF0) == 0xA000))
                            //    *(MMP_USHORT*)(jpeg_addr+0xF0) = 0xA000;
                            if(*(MMP_USHORT*)(jpeg_addr+0xEE) == 0xB800)
                                *(MMP_USHORT*)(jpeg_addr+0xEE) = 0xB400;
                            if(*(MMP_USHORT*)(jpeg_addr+0xEE) == 0x6000)
                                *(MMP_USHORT*)(jpeg_addr+0xEE) = 0x5A00;
                            //*********************************************
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_ph), jpeg_payload_size, 0);
                            PH_SET_TX_CTL(jpeg_ph->FRAME_H264_PH.dwFlag, 2);
                            PIPE_INFO(2, bDirty) = MMP_TRUE;
                            #if 0
                            dbg_printf(3,"MJ(%d)\r\n", jpeg_ph->FRAME_H264_PH.dwFrameSize);
                            #endif
                            send_count++;
                        }
                        #if Y_DATA_EN || RAW_DATA_EN
                        // 4st Y/RAW. valid frame
                        if((y_ph->FRAME_H264_PH.dwFrameSize) && (PH_GET_TX_CTL(y_ph->FRAME_H264_PH.dwFlag) == 1)){
                            y_payload_size = y_ph->FRAME_H264_PH.dwPayloadSize + FRAME_PAYLOAD_HEADER_SZ;
                            //if((y_ph->FRAME_H264_PH.dwFrameSeq%3) ==0){// 3 frame only output 1 frame for USB bandwidth issue.
                                MMPF_Video_AddDMABlk(0, (MMP_ULONG) (y_ph), y_payload_size, 0);
                            //}
                            PH_SET_TX_CTL(y_ph->FRAME_H264_PH.dwFlag, 2);
                            #if SUPPORT_PIPE_Y
                            PIPE_INFO(PIPE_Y, bDirty) = MMP_TRUE;
                            #else
                            PIPE_INFO(PIPE_G, bDirty) = MMP_TRUE;
                            #endif
                            #if 0
                            dbg_printf(3,"Y(%d)\r\n", y_ph->FRAME_H264_PH.dwFrameSize);
                            #endif
                            send_count++;
                        }
                        #if SUPPORT_AIT845x_MD
                        if(send_md_flag&&md_num) {
                            md_ph->FRAME_H264_PH.wVersion = 0x0090;
                            md_ph->FRAME_H264_PH.wImageOffset = UVC_H264_PH_LEN;
                            md_ph->FRAME_H264_PH.wStreamType = ST_AIT845x_MD;
                            md_ph->FRAME_H264_PH.dwFlag = 0x8000;

                            md_ph->FRAME_H264_PH.wImageWidth = 0;
                            md_ph->FRAME_H264_PH.wImageHeight = 0;
                            md_ph->FRAME_H264_PH.wFrameRate = 0;
                            md_ph->FRAME_H264_PH.dwFrameSeq = 0;
                            md_ph->FRAME_H264_PH.dwTimeStamp = 0;
                            md_ph->FRAME_H264_PH.dwFrameSize = md_num;
                            md_ph->FRAME_H264_PH.dwPayloadSize = ALIGN32(md_num);
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG)md_ph, ALIGN32(md_num) + FRAME_PAYLOAD_HEADER_SZ, 0);
                            send_md_flag = 0;
                            dbg_printf(3,"Send MD(%d)\r\n", md_num);
                            send_count++;
                        }
                        #endif
                        #endif
                        if(send_count == 0){
                             MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                             //RTNA_DBG_Str3("send 0 frame\r\n");
                        }
                    }
                }
                break;   
#endif                    
#if (SECS_VER > 20)
            case SKYPE_TX_STREAM:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->Common.dwPayloadSize ;
                #if 0
                RTNA_DBG_Str3("  skypetx len : ");
                RTNA_DBG_Long3(glFrameLength );
                RTNA_DBG_Str3("\r\n");
                #endif
                 {
#if DRAM_SIZE <= 2
                    MMP_ULONG max_ring_buf_size;
                    STREAM_CTL *cur_bctl;
#endif
                    FRAME_PAYLOAD_HEADER *yuv_ph2;
                    MMP_ULONG yuy2_addr2 ;
                    RES_TYPE_CFG *cur_res;
                    SKYPE_HEADER_SECTION *skype_hs;

                    usb_vc_advance_to_lastframe(stream_cfg, 0) ;


                    if(pipe0_cfg == PIPE_CFG_YUY2)
                        yuy2_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(0) ; // YUY2
                    else
                        yuy2_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(1) ; // YUY2

                    yuv_ph2 = (FRAME_PAYLOAD_HEADER *) yuy2_addr2 ;


                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        if(UvcSampleBuilder.main_size){
                            volatile MMP_UBYTE * yuy2_ptr = (volatile MMP_UBYTE *) yuy2_addr2;

                            cur_res = GetResCfg(glPccamResolution) ;
                            yuv_preview_size = cur_res->res_w * cur_res->res_h * 2;

                            // H264. valid frame
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt + FRAME_PAYLOAD_HEADER_SZ),
                                                 UvcSampleBuilder.main_size, 0);
                           {
                                cur_bctl = &(PIPE_INFO(0, b));

                                max_ring_buf_size = cur_bctl->slot_size - FRAME_PAYLOAD_HEADER_SZ - 64;

                                yuy2_ptr[FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size + 48 + 0] = HIBYTE(cur_res->res_w);
                                yuy2_ptr[FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size + 48 + 1] = LOBYTE(cur_res->res_w);
                                yuy2_ptr[FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size + 48 + 2] = HIBYTE(cur_res->res_h);
                                yuy2_ptr[FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size + 48 + 3] = LOBYTE(cur_res->res_h);

                                skype_hs = (SKYPE_HEADER_SECTION *)
                                           (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size);
                            }
                            //  dbg_printf(3,"(HZ,YUY2,H264) = (%d,%d,%d)\r\n",FRAME_PAYLOAD_HEADER_SZ,yuv_preview_size,UvcSample.main_size);


                            // Skype Header for preview stream
                            skype_hs->HDR0.dwPTS_H = SWAP_ULONG(Skype_PTS_H);  // 
                            skype_hs->HDR0.dwPTS_L = SWAP_ULONG(Skype_PTS_L);;  // 
                            skype_hs->HDR0.bStreamID = 1;  // 0: main stream, 1: preview stream
                            skype_hs->HDR0.bStreamType = SKYPE_FORMAT_YUY2;
                            skype_hs->HDR0.wFrameSeq = SWAP_USHORT(frame_ph->UVC_H264_PH.dwFrameSeq);  // big-endian, same as H264
                            skype_hs->HDR0.dwPayloadOffset = SWAP_ULONG(UvcSampleBuilder.main_size);
                            skype_hs->HDR0.dwPayloadSize = SWAP_ULONG(yuv_preview_size + 4);

                            // Skype Header for main stream
                            skype_hs->HDR1.dwPTS_H = SWAP_ULONG(Skype_PTS_H);  // 
                            skype_hs->HDR1.dwPTS_L = SWAP_ULONG(Skype_PTS_L);;  // 
                            skype_hs->HDR1.bStreamID = 0;  // 0: main stream, 1: preview stream
                            skype_hs->HDR1.bStreamType = SKYPE_FORMAT_H264;
                            skype_hs->HDR1.wFrameSeq = SWAP_USHORT(frame_ph->UVC_H264_PH.dwFrameSeq);  // big-endian
                            skype_hs->HDR1.dwPayloadOffset = 0;
                            skype_hs->HDR1.dwPayloadSize = SWAP_ULONG(UvcSampleBuilder.main_size);

                            skype_hs->dwHeaderNum = 0x02000000; // big-endian // 2;
                            skype_hs->dwMagicNum = 0x50594B53; // big-endian // 0x534B5950; "SKYP"
                             {
                                MMPF_Video_AddDMABlk(0,
                                                     (MMP_ULONG)
                                                     (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size + 48),
                                                     4, 0);
                                //TODO try to use another frame size instead
                                UvcSampleBuilder.main_size = yuv_preview_size;//yuv_ph2->UVC_H264_PH.dwPayloadSize;
                                if(IS_PIPE_RING(stream_cfg, 0)){
                                    MMP_LONG tx_len, left_len;

                                    left_len = UvcSampleBuilder.main_size;
                                    do{
                                        tx_len = VR_MIN(left_len, max_ring_buf_size);
                                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ),
                                                             tx_len, PIPE0_RING | DMA_BLK_SRC_IBC);
                                        left_len -= tx_len;
                                    }
                                    while(left_len > 0);
                                }
                                MMPF_Video_AddDMABlk(0,
                                                     (MMP_ULONG)
                                                     (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ + max_ring_buf_size),
                                                     sizeof(SKYPE_HEADER_SECTION), 0);
                            }
                        }
                        else{
                            RTNA_DBG_Str3("Lost H264 Frame\r\n");
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
                        }
                    }
                }
                break;   
#endif                       

#if SKYPE_UVC_H264
            case UVC_H264_STREAM:
                //Use common payload size
                //UvcSampleBuilder.main_size = frame_ph->SKYPE_UVC_H264_PH.dwPayloadSize;
                #if 0
                RTNA_DBG_Str3("  glFrameLength : ");
                RTNA_DBG_Long3(UvcSampleBuilder.main_size );
                RTNA_DBG_Str3("\r\n");
                #endif
                 {
                    FRAME_PAYLOAD_HEADER *yuv_ph2;
                    MMP_ULONG yuy2_addr2 ;
                    //SKYPE_HEADER_SECTION *skype_hs;
                    FRAME_PAYLOAD_HEADER *h264_ph;
                    MMP_ULONG app3_insert_addr = 0, app3_search_len;
                    MMP_UBYTE *jpeg_payload_ptr, *h264_ptr;// ,*h264_payload_ptr ;
                    MMP_UBYTE *yuy2_ptr, *yuy2_payload_ptr;

                    if(pipe0_cfg == PIPE_CFG_YUY2)
                        pipe = PIPE_0 ;
                    else
                        pipe = PIPE_1 ;

                    usb_vc_advance_to_lastframe(stream_cfg, pipe) ;

                    yuy2_addr2 = (MMP_ULONG) MMPF_Video_CurRdPtr(pipe) ;  // YUY2

                    yuv_ph2 = (FRAME_PAYLOAD_HEADER *) yuy2_addr2 ;

                    h264_ptr = (MMP_UBYTE *) ptt;
                    h264_ph = (FRAME_PAYLOAD_HEADER *) (h264_ptr);

                    jpeg_payload_ptr = (MMP_UBYTE *) gbJpegHeader;
                    app3_search_len = sizeof(gbJpegHeader);
                    yuy2_ptr = (MMP_UBYTE *) yuy2_addr2;
                    yuy2_payload_ptr = (yuy2_ptr + FRAME_PAYLOAD_HEADER_SZ);

                    // Force to send dummy frame
                    if(UvcSampleBuilder.nFrame == 0){
                        MMPF_Video_AddDMABlk(0, (MMP_ULONG) (yuy2_addr2 + FRAME_PAYLOAD_HEADER_SZ), 0, 0);
                        RTNA_DBG_Str3("send dummy frame\r\n");
                    }
                    else{
                        if(UvcSampleBuilder.main_size){
                            MMP_ULONG off ;//,*h264_ptr32;//,stream_bytes;
                            MMP_SHORT delay = 0;

                            UsbTransfer.PTS = h264_ph->SKYPE_UVC_H264_PH.dwTimeStamp;

                            app3_insert_addr = (MMP_ULONG) usb_uvc_search_app3_insert_addr((MMP_UBYTE *)
                                                                                           (jpeg_payload_ptr),
                                                                                           app3_search_len, 0xFFDD);
                            off = app3_insert_addr - (MMP_ULONG) jpeg_payload_ptr ;

                            // Header blk
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr), off, 0);

                            if(h264_ph->SKYPE_UVC_H264_PH.dwPayloadSize){
                                MMP_ULONG h264_blk_size = h264_ph->SKYPE_UVC_H264_PH.dwPayloadSize ;
                                MMP_ULONG tx_len , cur_addr,h264_off = 0;

                                if(delay){
                                    h264_ph->SKYPE_UVC_H264_PH.wDelay = delay ;
                                }

                                //h264_ph->SKYPE_UVC_H264_PH.dwTimeStamp = Skype_PTS;

                                h264_off = (UVC_H264_PH_LEN - h264_ph->SKYPE_UVC_H264_PH.wHeaderLen);  // start from valid header data

                                cur_addr = (MMP_ULONG) h264_ptr;//h264_payload_ptr ;
                                //h264_ptr32 = (MMP_ULONG *)(h264_payload_ptr);
                                h264_blk_size += (FRAME_PAYLOAD_HEADER_SZ - h264_off) ;

                                do{
                                    tx_len = (h264_blk_size > MAX_APP3_LEN) ? MAX_APP3_LEN : h264_blk_size ;
                                    MMPF_Video_AddDMABlk(DMA_BLK_JPEG_HDR_LEN, (MMP_ULONG) (cur_addr + h264_off),
                                                         tx_len, 0);
                                    h264_off += tx_len ;
                                    h264_blk_size -= tx_len ;
                                }
                                while(h264_blk_size) ;
                            }

                            // sean@2011_01_22, YUY2 payload insert 
                            if(yuv_ph2->SKYPE_UVC_H264_PH.dwPayloadSize && pipe0_cfg == (PIPE_CFG_YUY2)){
                                MMP_ULONG yuy2_blk_size = yuv_ph2->SKYPE_UVC_H264_PH.dwPayloadSize ;
                                MMP_ULONG tx_len,cur_addr,yuy2_off = 0;
                                MMP_ULONG max_ring_buf_size;
                                STREAM_CTL *cur_bctl;

                                if(delay){
                                    yuv_ph2->SKYPE_UVC_H264_PH.wDelay = delay ;
                                }                            

                                //yuv_ph2->SKYPE_UVC_H264_PH.dwTimeStamp = Skype_PTS;
                                cur_bctl = &(PIPE_INFO(0, b));
                                if(IS_PIPE_RING(stream_cfg, 0)){
                                    max_ring_buf_size = cur_bctl->slot_size - FRAME_PAYLOAD_HEADER_SZ;
                                }
                                else{
                                    max_ring_buf_size = 0xFFFFFFFF;
                                }

                                yuy2_off = (UVC_H264_PH_LEN - yuv_ph2->SKYPE_UVC_H264_PH.wHeaderLen);  // start from valid header data
                                DRBP("off:%d\r\n", yuy2_off);

                                yuy2_blk_size += (FRAME_PAYLOAD_HEADER_SZ - yuy2_off);//+=26
                                cur_addr = (MMP_ULONG) yuy2_ptr;
                                DRB(yuv_addr = (MMP_ULONG) yuy2_ptr);
                                if(IS_PIPE_RING(stream_cfg, 0)){
                                    MMP_LONG app3_len;
                                    MMP_UBYTE header;
                                    MMP_LONG ring_len;
                                    app3_len = MAX_APP3_LEN;
                                    ring_len = max_ring_buf_size + 26;
                                    DRBP("ring1:%d\r\n", ring_len);
                                    do{
                                        if(MAX_APP3_LEN == app3_len){
                                            header = DMA_BLK_JPEG_HDR_LEN;
                                        }
                                        else{
                                            header = 0;
                                        }
                                        tx_len = (yuy2_blk_size > ring_len) ? ring_len : yuy2_blk_size;
                                        DRBP("tx1:%d\r\n", tx_len);
                                        if(tx_len > app3_len){
                                            tx_len = app3_len;
                                            app3_len = MAX_APP3_LEN;
                                        }
                                        else{
                                            app3_len -= tx_len;
                                        }
                                        if(tx_len == ring_len){
                                            ring_len = max_ring_buf_size;
                                            DRBP("ring2:%d\r\n", ring_len);
                                        }
                                        else{
                                            ring_len -= tx_len;
                                        }
                                        MMPF_Video_AddDMABlk(header, (MMP_ULONG) (cur_addr + yuy2_off), tx_len,
                                                             PIPE0_RING | DMA_BLK_SRC_IBC);
                                        if(tx_len >= max_ring_buf_size){
                                            if(header == DMA_BLK_JPEG_HDR_LEN){
                                                yuy2_off = 32;
                                                DRBP("off A:%d\r\n", yuy2_off);
                                            }
                                        }
                                        else{
                                            yuy2_off += tx_len ;
                                            if(yuy2_off >= max_ring_buf_size){
                                                yuy2_off = 32;
                                                DRBP("off B:%d\r\n", yuy2_off);
                                            }
                                            DRBP("off C:%d\r\n", yuy2_off);
                                        }
                                        yuy2_blk_size -= tx_len ;
                                        //app3_len -= tx_len;

                                        if(yuy2_blk_size > 0x80000000){
                                            DBG_S(1, "yuy2_blk_size error\r\n");
                                            break;
                                        }
                                    }
                                    while(yuy2_blk_size > 0);
                                }
                                else{
                                    do{
                                        tx_len = (yuy2_blk_size > MAX_APP3_LEN) ? MAX_APP3_LEN : yuy2_blk_size ;
                                        MMPF_Video_AddDMABlk(DMA_BLK_JPEG_HDR_LEN, (MMP_ULONG) (cur_addr + yuy2_off),
                                                             tx_len, PIPE0_RING | DMA_BLK_SRC_IBC);
                                        yuy2_off += tx_len ;
                                        yuy2_blk_size -= tx_len ;
                                    }
                                    while(yuy2_blk_size) ;
                                }
                            }                           

                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (jpeg_payload_ptr + off), app3_search_len - off, 0);
                        }
                        else{
                            //if((yuv_ph2->SKYPE_UVC_H264_PH.dwPayloadSize)&&(!UvcSample.main_size)){
                            RTNA_DBG_Str3("Lost H264 Frame\r\n");
                            //}
                            MMPF_Video_AddDMABlk(0, (MMP_ULONG) (ptt), 0, 0);
                            //RTNA_DBG_Str3("Empty Frame\r\n");
                        }
                    }
                }
                break;
#endif
            default:
                dbg_printf(3, "Unknown gbCurH264Type %d\r\n", gbCurH264Type);
                return UVC_SEND_IMG_RET_END_FRAME;
                break;
            }
        } //if(m_VideoFmt
#if 0
        dbg_printf(3, "FLen = %d\r\n", UvcSampleBuilder.main_size);
#endif
#if SPEED_UP_PREVIEW_FRAME_RATE
        // reset all speed up DMA parameter
        // TODO consider move all these 0 to _uvc_tx_init
        UsbTransfer.bWaitDMADone = 0;
        UsbTransfer.pNextPayload = 0;
        UsbTransfer.usb_dma_len = 0;
#endif
        UsbTransfer.fb.ProcSize = 0;
        UsbTransfer.fb.bKeepSending = 0;
        UsbTransfer.fb.phase = RT_TX_IDLE;
    }//if(UvcSample.packet_count == 0)

    endbit = _uvc_send_blk(sti_mode);

    return (endbit == UVC_EOF) ? UVC_SEND_IMG_RET_END_FRAME : UVC_SEND_IMG_RET_CONTINUE;
}

#if CAPTURE_BAYER_RAW_ENABLE
//
// Return captured size. (glPCCamJpegSize)
//
MMP_ULONG usb_vc_take_raw_picture(MMP_UBYTE raw_mode, MMP_ULONG srcAddr, MMP_ULONG dstAddr)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_UBYTE   vid = 0;
    MMP_ULONG size ,raw_w,raw_h;
    MMP_UBYTE *buf_addr ;

    RTNA_DBG_Str3("take raw pict...\r\n");

    USB_TakeRawPicture(PCAM_BLOCKING, srcAddr + FRAME_PAYLOAD_HEADER_SZ) ;

    raw_w = (pVIF->VIF_GRAB[vid].PIXL_ED - pVIF->VIF_GRAB[vid].PIXL_ST + 1);
    raw_h = (pVIF->VIF_GRAB[vid].LINE_ED - pVIF->VIF_GRAB[vid].LINE_ST + 1);

    size = (raw_mode == 0) ? ((raw_w) * (raw_h) * 4 / 3) : (raw_w) * (raw_h);

    FB_BASE_B[srcAddr + 28] = (MMP_UBYTE) (size >> 24) & 0xFF;
    FB_BASE_B[srcAddr + 29] = (MMP_UBYTE) (size >> 16) & 0xFF;
    FB_BASE_B[srcAddr + 30] = (MMP_UBYTE) (size >> 8) & 0xFF;
    FB_BASE_B[srcAddr + 31] = (MMP_UBYTE) (size & 0xFF);

    RTNA_DBG_Str3("Raw Data Src Addr:");RTNA_DBG_Long3(srcAddr);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("Raw Data Dst Addr:");RTNA_DBG_Long3(dstAddr);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("Raw Data Size    :");RTNA_DBG_Long3(size);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("Raw Data W    :");RTNA_DBG_Long3(raw_w);RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("Raw Data H   :");RTNA_DBG_Long3(raw_h);RTNA_DBG_Str3("\r\n");

    buf_addr = (MMP_UBYTE *) (srcAddr); 
    usb_uvc_fill_payload_header((MMP_UBYTE *) buf_addr, ALIGN32(size), 0, 0, PTS, raw_w, raw_h, ST_MJPEG,
                                ISP_IF_AE_GetRealFPS());
    //    MMPF_USB_ReleaseDm();

    RTNA_DBG_Str3("take raw pict...end\r\n");
    return size ;
}
#endif

void usb_vc_vci_cs(MMP_UBYTE req)
{
    MMP_UBYTE cs;
    //    volatile MMP_UBYTE *USB_REG_BASE_B = (volatile MMP_UBYTE *) USB_CTL_BASE_ADDR;   

    cs = (UsbRequestPayload_wValue >> 8);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    switch(cs){
    case VC_VIDEO_POWER_MODE_CONTROL:
        // under coding
        usb_vc_stall(CONTROL_UNKNOWN);
        break;
    case VC_REQUEST_ERROR_CODE_CONTROL:
        usb_vc_cmd_cfg(req, &VCI_ERROR_CFG, (CMD_VALUE) gbVCERRCode);    
        break;
#if 0
case VC_CONTROL_UNDEFINED:
case VC_RESERVED:
#endif
    default:
        // un-support
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}

#if SUPPORT_SU
void usb_vc_su_cs(MMP_UBYTE req)
{
    MMP_UBYTE cs;
    //   volatile MMP_UBYTE *USB_REG_BASE_B = (volatile MMP_UBYTE *) USB_CTL_BASE_ADDR;   

    cs = (UsbRequestPayload_wValue >> 8);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);

    switch(cs){
    case SU_INPUT_SELECT_CONTROL:
        usb_vc_cmd_cfg(req, &SU_INPUT_SELECT_CFG, (CMD_VALUE) 0x01);
        break;
        //case SU_CONTROL_UNDEFINED:
    default:
        // un-support
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}
#endif

void usb_vc_ct_cs(MMP_UBYTE req)
{
    MMP_UBYTE cs;

    cs = (UsbRequestPayload_wValue >> 8);

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    switch(cs){
#if (CUSTOMER != NMG)// && (CUSTOMER != CCN)
    case CT_AE_MODE_CONTROL:
        usb_vc_cmd_cfg(req, &CT_AE_MODE_CFG, (CMD_VALUE) gbAE);  
        break;
#endif            
#if (CUSTOMER != NMG)// && (CUSTOMER != CCN) //TODO consider use feature instead of customer id
    case CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
        CT_EXPOSURE_TIME_ABS_CFG.bInfoCap = gbEVInfo;
        usb_vc_cmd_cfg(req, &CT_EXPOSURE_TIME_ABS_CFG, (CMD_VALUE) gsEV);  
        break;
#endif
#if SUPPORT_AUTO_FOCUS
    case CT_FOCUS_ABSOLUTE_CONTROL:
        usb_vc_cmd_cfg(req, &CT_FOCUS_ABS_CFG, (CMD_VALUE) gsAFocus);  
        break;       
#endif
#if SUPPORT_AUTO_FOCUS
    case CT_FOCUS_AUTO_CONTROL:
        usb_vc_cmd_cfg(req, &CT_FOCUS_AUTO_CFG, (CMD_VALUE) gbAutoFocus);  
        break;       
#endif
#if SUPPORT_DIGITAL_ZOOM
    case CT_ZOOM_ABSOLUTE_CONTROL:
        if(USB_IsPreviewActive()){
            //CT_ZOOM_ABS_CFG.bInfoCap |=  INFO_ASYNC_CONTROL_SUPPORT ;
        }
        else{
            //CT_ZOOM_ABS_CFG.bInfoCap &= ~INFO_ASYNC_CONTROL_SUPPORT ;
        }
        usb_vc_cmd_cfg(req, &CT_ZOOM_ABS_CFG, (CMD_VALUE) gsZoom);  
        break;       
#endif   
#if SUPPORT_DIGITAL_PAN || (UVC_IT_BITMAP & (1 << 11))
    case CT_PANTILT_ABSOLUTE_CONTROL:
         {
            MMP_ULONG curVal[2] ;
            curVal[0] = glPan ;
            curVal[1] = glTilt ;
#if 0
if(USB_IsPreviewActive()) {
    //CT_PANTILT_ABS_CFG.bInfoCap |=  INFO_ASYNC_CONTROL_SUPPORT ;
} else {
    //CT_PANTILT_ABS_CFG.bInfoCap &= ~INFO_ASYNC_CONTROL_SUPPORT ;
}
#endif
            usb_vc_cmd_cfg(req, &CT_PANTILT_ABS_CFG, (CMD_VALUE) curVal);  
            break;
        }
#endif
#if (UVC_IT_BITMAP & (1 << 12))
    case CT_PANTILT_RELATIVE_CONTROL:
        usb_vc_cmd_cfg(req, &CT_PANTILT_RELATIVE_CFG, (CMD_VALUE) & CT_PANTILT_RELATIVE_CFG.dwCurVal);
        break;
#endif
#if UVC_IT_BITMAP & (1 << 13)
    case CT_ROLL_ABSOLUTE_CONTROL:
         {
#if (ASU_CAMERA_APP_VERSION > 29)
            ISP_AF_RESULT bResult;
            bResult = ISP_IF_AF_GetResult();
            //dbg_printf(0, "!CT:%02X, R=%d, ", cs, bResult);
            switch(bResult){
            case ISP_AF_RESULT_MOVING:
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) (MMP_USHORT) (1 << 8);//busy
                break;
            case ISP_AF_RESULT_FOCUSED:
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) (MMP_USHORT) (0 << 8);//reached=>idle
                break;
            case ISP_AF_RESULT_MISSED:
            default:
                if(ISP_IF_3A_GetSwitch(ISP_3A_ALGO_AF)){
                    CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) (MMP_USHORT) (3 << 8);//fail
                }
                else{
                    CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) (MMP_USHORT) (0 << 8);//stop==>idle
                }
                break;
            }
            //dbg_printf(0, "0x%04X,\r\n", CT_ROLL_ABS_CFG.dwCurVal);
#elif (ASU_CAMERA_APP_VERSION > 23)
            ISP_AF_RESULT bResult;
            bResult = ISP_IF_AF_GetResult();
            //dbg_printf(0, "!CT:%02X, R=%d, ", cs, bResult);
            switch(bResult){
            case ISP_AF_RESULT_MOVING:
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 1;//busy
                break;
            case ISP_AF_RESULT_FOCUSED:
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 0;//reached=>idle
                break;
            case ISP_AF_RESULT_MISSED:
            default:
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 3;//fail
                break;
            }
            //dbg_printf(0, "%02X,\r\n", CT_ROLL_ABS_CFG.dwCurVal);
#endif
            usb_vc_cmd_cfg(req, &CT_ROLL_ABS_CFG, (CMD_VALUE) CT_ROLL_ABS_CFG.dwCurVal);
        }
        break;
#endif
#if UVC_IT_BITMAP & (1 << 21)
    case CT_REGION_OF_INTEREST:
        usb_vc_cmd_cfg(req, &CT_ROI_CFG, (CMD_VALUE) & CT_ROI_CFG.dwCurVal);
        break;
#endif
#if 0          
        case CT_CONTROL_UNDEFINED:
        case CT_SCANNING_MODE_CONTROL:
        case CT_AE_PRIORITY_CONTROL:
        case CT_EXPOSURE_TIME_RELATIVE_CONTROL:
        case CT_FOCUS_RELATIVE_CONTROL:
        case CT_IRIS_ABSOLUTE_CONTROL:
        case CT_IRIS_RELATIVE_CONTROL:
        case CT_PANTILT_RELATIVE_CONTROL:
        case CT_ROLL_ABSOLUTE_CONTROL:
        case CT_ROLL_RELATIVE_CONTROL:
        case CT_PRIVACY_CONTROL:
invalid_ct:
#endif        
    default:
        // un-support
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}


void usb_vc_pu_cs(MMP_UBYTE req)
{
    MMP_UBYTE cs;
    //    volatile MMP_UBYTE *USB_REG_BASE_B = (volatile MMP_UBYTE *) USB_CTL_BASE_ADDR;   
    cs = (UsbRequestPayload_wValue >> 8);
    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    switch(cs){
    case PU_BACKLIGHT_COMPENSATION_CONTROL:
        usb_vc_cmd_cfg(req, &PU_BACKLIGHT_CFG, (CMD_VALUE) gsBacklight);
        break;
    case PU_BRIGHTNESS_CONTROL:
        usb_vc_cmd_cfg(req, &PU_BRIGHTNESS_CFG, (CMD_VALUE) gsBrightness);
        break;
    case PU_CONTRAST_CONTROL:
        usb_vc_cmd_cfg(req, &PU_CONTRAST_CFG, (CMD_VALUE) gsContrast);
        break;
    case PU_POWER_LINE_FREQUENCY_CONTROL:
        usb_vc_cmd_cfg(req, &PU_POWERLINEREQ_CFG, (CMD_VALUE) gbBandFilter); 
        break;
    case PU_HUE_CONTROL:
        usb_vc_cmd_cfg(req, &PU_HUE_CFG, (CMD_VALUE) gsHue);
        break;
    case PU_SATURATION_CONTROL:
        usb_vc_cmd_cfg(req, &PU_SATURATION_CFG, (CMD_VALUE) gsSaturation);
        break;
    case PU_SHARPNESS_CONTROL:
        usb_vc_cmd_cfg(req, &PU_SHARPNESS_CFG, (CMD_VALUE) gsSharpness);
        break;
    case PU_GAMMA_CONTROL:
        usb_vc_cmd_cfg(req, &PU_GAMMA_CFG, (CMD_VALUE) gsGamma);
        break;
    case PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
        PU_WB_TEMP_CFG.bInfoCap = gbTemperInfo;
        usb_vc_cmd_cfg(req, &PU_WB_TEMP_CFG, (CMD_VALUE) gsTemper);
        break;
    case PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
        usb_vc_cmd_cfg(req, &PU_WB_TEMP_AUTO_CFG, (CMD_VALUE) gbAWB);
        break;
    case PU_GAIN_CONTROL:
#if (CUSTOMER == NMG)// || (CUSTOMER == CCN)
        goto invalid_pu;
#else
        //PU_GAIN_CFG.bInfoCap = gbGainInfo;
        usb_vc_cmd_cfg(req, &PU_GAIN_CFG, (CMD_VALUE) gsGain);
#endif
        break;
#if 0
        case PU_CONTROL_UNDEFINED:
        case PU_WHITE_BALANCE_COMPONENT_CONTROL:
        case PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
        case PU_DIGITAL_MULTIPLIER_CONTROL:
        case PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
        case PU_HUE_AUTO_CONTROL:
        case PU_ANALOG_VIDEO_STANDARD_CONTROL:
        case PU_ANALOG_LOCK_STATUS_CONTROL:
#endif
        //invalid_pu:        
    default:
        // un-support
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}

/*
#define EU1_CMD1_MIN (0x0)
#define EU1_CMD1_MAX (0xFFFFFF)
#define EU1_CMD1_DEF (0x341234)

#define EU1_CMD2_MIN (0x0)
#define EU1_CMD2_MAX (0xFFFF)
#define EU1_CMD2_DEF (0x2030)

#define EU1_CMD3_LEN 0x10   //16bytes
MMP_ULONG eu1_cmd1_value;
MMP_USHORT eu1_cmd2_value;
*/

//20091225
//MMP_UBYTE  eu2_cmd1_value;



#if CAPTURE_RAW_XU
RAW_CAPTURE_FORMAT gRawFormat;
#endif

#define USE_PUT_FUNCTION_IN_VSI 1 //set 1 to use USB put functions in probe commit features

#if USE_PUT_FUNCTION_IN_VSI
//commit uses this as well
VC_CMD_CFG VC_VSI_PROBE_CFG = {
(CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | \
CAP_GET_LEN_CMD | CAP_GET_INFO_CMD | CAP_GET_DEF_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
sizeof(vp),
(CMD_VALUE) 0,(CMD_VALUE) & vp, //RES, DEF
(CMD_VALUE) & vp,(CMD_VALUE) & vp,(CMD_VALUE) & vp //MIN, MAX, CUR
};

VC_CMD_CFG VC_VSI_STILL_PROBE_CFG = {
(CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | CAP_GET_MIN_CMD | CAP_GET_MAX_CMD | \
CAP_GET_LEN_CMD | CAP_GET_INFO_CMD | CAP_GET_DEF_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
sizeof(sp),
(CMD_VALUE) 0,(CMD_VALUE) & sp, //RES, DEF
(CMD_VALUE) & sp,(CMD_VALUE) & sp,(CMD_VALUE) & sp //MIN, MAX, CUR
};

VC_CMD_CFG VC_VSI_STILL_COMMIT_CFG = {
(CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | \
CAP_GET_LEN_CMD | CAP_GET_INFO_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
sizeof(sc),
(CMD_VALUE) 0,(CMD_VALUE) 0, //RES, DEF
(CMD_VALUE) 0,(CMD_VALUE) 0,(CMD_VALUE) & sc //MIN, MAX, CUR
};

VC_CMD_CFG VC_VSI_STILL_TRIGGER_CFG = {
(CAP_SET_CUR_CMD | CAP_GET_CUR_CMD | \
CAP_GET_INFO_CMD),
(INFO_GET_SUPPORT | INFO_SET_SUPPORT),
sizeof(gbTriOP),
(CMD_VALUE) 0,(CMD_VALUE) 0, //RES, DEF
(CMD_VALUE) 0,(CMD_VALUE) 0,(CMD_VALUE) 0 //MIN, MAX, CUR
};

void usb_vc_vsi_cs(MMP_UBYTE req)//interface control request
{
#if (USING_STILL_METHOD_1 == 0)
    STILL_PROBE temp_sp;
#endif
    MMP_UBYTE cs;
    cs = (UsbRequestPayload_wValue >> 8);//control selector

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
    switch(cs){
    case VS_PROBE_CONTROL:
#if USB_UVC_BULK_EP         
        LinuxProbeCheck = 1;
#endif
        switch(req){
        case GET_CUR_CMD:
            usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 1);
#if USB_UVC_BULK_EP  // tomy@2010_09_01, to fix Skype preview issue via BULK transfer on some linux OS
            gbCheckSystemInitFlag++;
            if(gbCheckSystemInitFlag >= 254)
                gbCheckSystemInitFlag = 254;
#endif
            break;
        case GET_MIN_CMD:
            //usb_vc_get_video_probe(gbCurFormatIndex,1,0);
            usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 0);
            break;
        case GET_MAX_CMD:
#if USB_UVC_BULK_EP
            gbProbeSetCur = 0;
#endif
            switch(gbCurFormatIndex){
#if ENABLE_YUY2
            case YUY2_FORMAT_INDEX:
                //YVY2
                //usb_vc_get_video_probe(gbCurFormatIndex, NUM_D1_YUY2_VIDEO,0);
                usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 0);
                break;
#endif
#ifdef ENABLE_UYVY
            case UYVY_FORMAT_INDEX:
                //UYVY
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_UYVY_VIDEO, 0);
                break;
#endif
#if ENABLE_MJPEG
            case MJPEG_FORMAT_INDEX:
                //MJPEG
#if SUPPORT_DUAL_DEVICE
                usb_vc_get_video_probe(gbCurFormatIndex,
                                       (UsbRequestPayload_wIndex ==
                                        UVC_D1_STREAM_IF1_NO ?
                                        NUM_D1_MJPG_VIDEO :
                                        NUM_D2_MJPG_VIDEO),
                                       0);
#elif SUPPORT_SWITCH_CAMERA
                usb_vc_get_video_probe(gbCurFormatIndex,
                                       ((gbSwitchSensor == MAIN_SENSOR) ? NUM_D1_MJPG_VIDEO : NUM_D2_MJPG_VIDEO), 0);
#else
                //usb_vc_get_video_probe(gbCurFormatIndex, NUM_D1_MJPG_VIDEO,0);
                usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 0);
#endif
                break;
#endif
#if ENABLE_FRAME_BASE_H264
            case FRAME_BASE_H264_INDEX:
                //FRAME BASE H264
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_H264_VIDEO, 0);
                break;
#endif
            }
            break;
        case GET_DEF_CMD:
#if USB_UVC_BULK_EP
            gbProbeSetCur = 1;
#endif
            usb_vc_get_video_probe(gbCurFormatIndex, 1, 1);
            break;
        }
        usb_vc_cmd_cfg(req, &VC_VSI_PROBE_CFG, VC_VSI_PROBE_CFG.dwCurVal);
        break;
    case VS_COMMIT_CONTROL:
        switch(req){
        case GET_CUR_CMD:
#if BLOCK_2_UVC_INTERFACE
             {
                MMP_BOOL IsPreviewEnable;

                MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
                dbg_printf(0, " VS_COMMIT, IsPreviewEnable:%d\r\n", IsPreviewEnable);
                if(IsPreviewEnable){
                    dbg_printf(0, "  ! Curr=%d, New=%d, _NOT_READY\r\n", gbCurrentSensor, UsbRequestPayload_wIndex);
                    usb_vc_stall(CONTROL_NOT_READY);
                    break;
                }
            }
#endif

            //usb_vc_get_video_probe(framemode);
            usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 1);

            break;
        }
        usb_vc_cmd_cfg(req, &VC_VSI_PROBE_CFG, VC_VSI_PROBE_CFG.dwCurVal);
        break;
#if (USING_STILL_METHOD_1 == 0)
    case VS_STILL_PROBE_CONTROL:
        switch(req){
        case GET_CUR_CMD:
            //usb_vc_get_still_probe(gbCurStillFrameIndex);
            //usb_vc_get_still_probe(&sp);
            break;
        case GET_MIN_CMD:
            usb_vc_get_still_probe(gbCurStillFormatIndex, 1, &temp_sp);
            //Truman@121113 bug fix: original it was pointed to tmpptr!
            VC_VSI_STILL_PROBE_CFG.dwMinVal = (CMD_VALUE) & temp_sp;
            //usb_vc_get_still_probe(1);
            break;
        case GET_MAX_CMD:
            switch(gbCurStillFormatIndex){
#if ENABLE_YUY2
            case YUY2_FORMAT_INDEX:
                //YVY2
                usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_YUY2_STILL, &temp_sp);
                break;
#endif
#ifdef ENABLE_UYVY
            case UYVY_FORMAT_INDEX:
                //UYVY
                usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_UYVY_STILL, &temp_sp);
                break;
#endif
#if ENABLE_MJPEG
            case MJPEG_FORMAT_INDEX:
                //MJPEG
                usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_MJPG_STILL, &temp_sp);
                break;
#endif
            }
            //Truman@121113 bug fix: original it was pointed to tmpptr!
            VC_VSI_STILL_PROBE_CFG.dwMaxVal = (CMD_VALUE) & temp_sp;
            break;
        case GET_DEF_CMD:
            usb_vc_get_still_probe(1, 1, &temp_sp);
            VC_VSI_STILL_PROBE_CFG.dwDefVal = (CMD_VALUE) & temp_sp;
            // usb_vc_get_still_probe(2);
            break;
        }
        DBG_S(3, "[sp]\r\n");
        usb_vc_cmd_cfg(req, &VC_VSI_STILL_PROBE_CFG, VC_VSI_STILL_PROBE_CFG.dwCurVal);
        break;
    case VS_STILL_COMMIT_CONTROL:
        DBG_S(3, "[sc]\r\n");
        usb_vc_cmd_cfg(req, &VC_VSI_STILL_COMMIT_CFG, VC_VSI_STILL_COMMIT_CFG.dwCurVal);
        break;
    case VS_STILL_IMAGE_TRIGGER_CONTROL:
        switch(req){
        case GET_CUR_CMD:
            VC_VSI_STILL_TRIGGER_CFG.dwCurVal = (CMD_VALUE) gbTriOP;
            break;
        }
        usb_vc_cmd_cfg(req, &VC_VSI_STILL_TRIGGER_CFG, VC_VSI_STILL_TRIGGER_CFG.dwCurVal);
        break;
#endif  // #if (USING_STILL_METHOD_1 == 0)
    default:
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}
#else
void usb_vc_vsi_cs(MMP_UBYTE req)//interface control request
{
    MMP_UBYTE cs,cap;
    MMP_USHORT i;
    MMP_USHORT *tmpptr;
#if (USING_STILL_METHOD_1 == 0)
    MMP_UBYTE *tmpptrb;
#endif
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;   

    cs = (UsbRequestPayload_wValue >> 8);//control selector

    UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
#if 0
    RTNA_DBG_Str3("VSI :[\r\n");
    RTNA_DBG_Str3("CS :");
    RTNA_DBG_Byte3(cs);
    RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("REQ :");
    RTNA_DBG_Byte3(req);
    RTNA_DBG_Str3("\r\n");
    RTNA_DBG_Str3("Len :");
    RTNA_DBG_Byte3(UsbRequestPayload_wLength);
    RTNA_DBG_Str3("]\r\n");
    
#endif
    switch(cs){
    case VS_PROBE_CONTROL:
#if USB_UVC_BULK_EP         
        LinuxProbeCheck = 1;
#endif
        switch(req){
        case SET_CUR_CMD:
            USBOutPhase = req;
            USBOutData = 1;        
            break;
        case GET_CUR_CMD:
            USBInPhase = req;
            tmpptr = (MMP_USHORT *) &vp;
            /*
            RTNA_DBG_Str(0, " ** GET_CUR_CMD: gbCurFormatIndex = "); 
            RTNA_DBG_Short(0, gbCurFormatIndex);     
            RTNA_DBG_Str(0, " **\r\n"); 
            */
            //usb_vc_get_video_probe(framemode);
            usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 1);

#if USB_UVC_BULK_EP  // tomy@2010_09_01, to fix Skype preview issue via BULK transfer on some linux OS
            gbCheckSystemInitFlag++;
            if(gbCheckSystemInitFlag >= 254)
                gbCheckSystemInitFlag = 254;
#endif    

            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt / 2;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & (*(tmpptr + i));
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & ((*(tmpptr + i)) >> 8);
            }
            usb_ep0_in();
            break;
        case GET_MIN_CMD:
            USBInPhase = req;
            tmpptr = (MMP_USHORT *) &vp;

            //RTNA_DBG_Str(0, " ** GET_MIN_CMD: gbCurFormatIndex = "); 
            //RTNA_DBG_Short(0, gbCurFormatIndex);     
            //RTNA_DBG_Str(0, " **\r\n"); 

            //usb_vc_get_video_probe(1);
            usb_vc_get_video_probe(gbCurFormatIndex, 1, 0);

            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt / 2;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & (*(tmpptr + i));
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & ((*(tmpptr + i)) >> 8);
            }
            usb_ep0_in();           
            break;
        case GET_MAX_CMD:
            USBInPhase = req;
#if USB_UVC_BULK_EP            
            gbProbeSetCur = 0;
#endif           
            tmpptr = (MMP_USHORT *) &vp;

            //RTNA_DBG_Str(0, " ** GET_MAX_CMD: gbCurFormatIndex = "); 
            //RTNA_DBG_Short(0, gbCurFormatIndex);     
            //RTNA_DBG_Str(0, " **\r\n"); 

            //usb_vc_get_video_probe(2);
            switch(gbCurFormatIndex){
#if ENABLE_YUY2
            case YUY2_FORMAT_INDEX:
                //YVY2
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_D1_YUY2_VIDEO, 0);
                break;
#endif
#ifdef ENABLE_UYVY
            case UYVY_FORMAT_INDEX:
                //UYVY
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_UYVY_VIDEO, 0);
                break;
#endif
#if ENABLE_MJPEG
            case MJPEG_FORMAT_INDEX:
                //MJPEG
#if SUPPORT_DUAL_DEVICE
                usb_vc_get_video_probe(gbCurFormatIndex,
                                       (UsbRequestPayload_wIndex ==
                                        UVC_D1_STREAM_IF1_NO ?
                                        NUM_D1_MJPG_VIDEO :
                                        NUM_D2_MJPG_VIDEO),
                                       0);
#elif SUPPORT_SWITCH_CAMERA
                usb_vc_get_video_probe(gbCurFormatIndex,
                                       ((gbSwitchSensor == MAIN_SENSOR) ? NUM_D1_MJPG_VIDEO : NUM_D2_MJPG_VIDEO), 0);
#else
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_D1_MJPG_VIDEO, 0);
#endif
                break;
#endif
#if ENABLE_FRAME_BASE_H264
            case FRAME_BASE_H264_INDEX:
                //FRAME BASE H264
                usb_vc_get_video_probe(gbCurFormatIndex, NUM_H264_VIDEO, 0);
                break;
#endif
            }


            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt / 2;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & (*(tmpptr + i));
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & ((*(tmpptr + i)) >> 8);
            }
            usb_ep0_in();           
            break;
        case GET_RES_CMD:
            // under coding
            usb_vc_stall(CONTROL_UNKNOWN);
            break;
        case GET_LEN_CMD:
            USBInPhase = req;
            USBEP0TxCnt = 0x02;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x1A;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x00;
            usb_ep0_in();
            break;
        case GET_INFO_CMD:
            USBInPhase = req;
            cap = INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            USBEP0TxCnt = 0x01;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = cap;
            usb_ep0_in();
            break;
        case GET_DEF_CMD:
            USBInPhase = req;
#if USB_UVC_BULK_EP            
            gbProbeSetCur = 1;
#endif
            tmpptr = (MMP_USHORT *) &vp;
            //usb_vc_get_video_probe(1);

            //RTNA_DBG_Str(0, " ** GET_DEF_CMD: gbCurFormatIndex = "); 
            //RTNA_DBG_Short(0, gbCurFormatIndex);     
            //RTNA_DBG_Str(0, " **\r\n"); 

            usb_vc_get_video_probe(gbCurFormatIndex, 1, 1);
            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt / 2;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & (*(tmpptr + i));
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & ((*(tmpptr + i)) >> 8);
            }
            usb_ep0_in();
            break;
        default:
            // un-support
            usb_vc_stall(CONTROL_INVALID_REQUEST);
            break;
        }        
        break;
    case VS_COMMIT_CONTROL:
        switch(req){
        case SET_CUR_CMD:
            USBOutPhase = req;
            USBOutData = 1;     
            break;
        case GET_CUR_CMD:
            USBInPhase = req;
            tmpptr = (MMP_USHORT *) &vp;

#if BLOCK_2_UVC_INTERFACE
             {
                MMP_BOOL IsPreviewEnable;

                MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
                dbg_printf(0, " VS_COMMIT, IsPreviewEnable:%d\r\n", IsPreviewEnable);
                if(IsPreviewEnable){
                    dbg_printf(0, "  ! Curr=%d, New=%d, _NOT_READY\r\n", gbCurrentSensor, UsbRequestPayload_wIndex);
                    usb_vc_stall(CONTROL_NOT_READY);
                    break;
                }
            }
#endif

            //usb_vc_get_video_probe(framemode);
            usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 1);

            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt / 2;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & (*(tmpptr + i));
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0xFF & ((*(tmpptr + i)) >> 8);
            }
            usb_ep0_in();
            break;
        case GET_LEN_CMD:
            USBInPhase = req;           
            USBEP0TxCnt = 0x02;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x1A;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x00;
            usb_ep0_in();
            break;
        case GET_INFO_CMD:
            USBInPhase = req;           
            cap = INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            USBEP0TxCnt = 0x01;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = cap;
            usb_ep0_in();
            break;
            //case GET_MIN_CMD:
            //case GET_MAX_CMD:
            //case GET_RES_CMD:
            //case GET_DEF_CMD:
        default:
            // un-support
            usb_vc_stall(CONTROL_INVALID_REQUEST);
            break;
        }        
        break;
#if (USING_STILL_METHOD_1 == 0)
    case VS_STILL_PROBE_CONTROL:
        switch(req){
        case SET_CUR_CMD:
            USBOutPhase = req;
            USBOutData = 1;        
            break;
        case GET_CUR_CMD:
            USBInPhase = req;
            tmpptrb = (MMP_UBYTE *) &sp;
            //usb_vc_get_still_probe(gbCurStillFrameIndex);
            //usb_vc_get_still_probe(&sp);
            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptrb + i);
            }
            usb_ep0_in();
            break;
        case GET_MIN_CMD:
             {
                STILL_PROBE temp_sp;
                usb_vc_get_still_probe(gbCurStillFormatIndex, 1, &temp_sp);
                USBInPhase = req;
                tmpptrb = (MMP_UBYTE *) &temp_sp; //&sp;
                //usb_vc_get_still_probe(1);

                USBEP0TxCnt = UsbRequestPayload_wLength;
                for(i = 0;i < USBEP0TxCnt;i++){
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptr + i);
                }
                usb_ep0_in();
            }           
            break;
        case GET_MAX_CMD:
            /*
                USBInPhase = req;
                tmpptrb = (MMP_UBYTE *) &sp;
                usb_vc_get_still_probe(3);
                USBEP0TxCnt = UsbRequestPayload_wLength;
                for(i = 0;i < USBEP0TxCnt;i++) {
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptr + i);
                }
                usb_ep0_in();           
            */
            {
                STILL_PROBE temp_sp;                
                USBInPhase = req;

                switch(gbCurStillFormatIndex){
#if ENABLE_YUY2
                case YUY2_FORMAT_INDEX:
                    //YVY2
                    usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_YUY2_STILL, &temp_sp);
                    break;
#endif
#ifdef ENABLE_UYVY
                case UYVY_FORMAT_INDEX:
                    //UYVY
                    usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_UYVY_STILL, &temp_sp);
                    break;
#endif
#if ENABLE_MJPEG
                case MJPEG_FORMAT_INDEX:
                    //MJPEG
                    usb_vc_get_still_probe(gbCurStillFormatIndex, NUM_MJPG_STILL, &temp_sp);
                    break;
#endif
                }

                tmpptrb = (MMP_UBYTE *) &temp_sp;
                USBEP0TxCnt = UsbRequestPayload_wLength;
                for(i = 0;i < USBEP0TxCnt;i++){
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptr + i);
                }
                usb_ep0_in();
            }    
            break;
        case GET_RES_CMD:
            // under coding
            usb_vc_stall(CONTROL_UNKNOWN);
            break;
        case GET_LEN_CMD:
            USBInPhase = req;
            USBEP0TxCnt = 0x02;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x0B;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x00;
            usb_ep0_in();
            break;
        case GET_INFO_CMD:
            USBInPhase = req;
            cap = INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            USBEP0TxCnt = 0x01;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = cap;
            usb_ep0_in();
            break;
        case GET_DEF_CMD:
             {
                STILL_PROBE temp_sp;
                usb_vc_get_still_probe(1, 1, &temp_sp);
                USBInPhase = req;
                tmpptr = (MMP_USHORT *) &temp_sp;//&vp;
                // usb_vc_get_still_probe(2);
                USBEP0TxCnt = UsbRequestPayload_wLength;
                for(i = 0;i < USBEP0TxCnt;i++){
                    pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptr + i);
                }
                usb_ep0_in();
            }
            break;
        default:
            // un-support
            usb_vc_stall(CONTROL_INVALID_REQUEST);
            break;
        }        
        break;
    case VS_STILL_COMMIT_CONTROL:
        switch(req){
        case SET_CUR_CMD:
            USBOutPhase = req;
            USBOutData = 1;           
            break;
        case GET_CUR_CMD:
            USBInPhase = req;
            //tmpptrb = (MMP_UBYTE *) &sp;
            tmpptrb = (MMP_UBYTE *) &sc;
            //usb_vc_get_still_probe(gbCurStillFrameIndex);
            USBEP0TxCnt = UsbRequestPayload_wLength;
            for(i = 0;i < USBEP0TxCnt;i++){
                pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = *(tmpptr + i);
            }
            usb_ep0_in();
            break;
        case GET_LEN_CMD:
            USBInPhase = req;           
            USBEP0TxCnt = 0x02;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x0B;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = 0x00;
            usb_ep0_in();
            break;
        case GET_INFO_CMD:
            USBInPhase = req;           
            cap = INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            USBEP0TxCnt = 0x01;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = cap;
            usb_ep0_in();
            break;
            //case GET_MIN_CMD:
            //case GET_MAX_CMD:
            //case GET_RES_CMD:
            //case GET_DEF_CMD:
        default:
            // un-support
            usb_vc_stall(CONTROL_INVALID_REQUEST);
            break;
        }        
        break;
    case VS_STILL_IMAGE_TRIGGER_CONTROL:
        switch(req){
        case SET_CUR_CMD:
            USBOutPhase = req;
            USBOutData = 1;          
            break;
        case GET_CUR_CMD:
            USBInPhase = req;
            USBEP0TxCnt = 1;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = gbTriOP;
            usb_ep0_in();
            break;
        case GET_INFO_CMD:
            USBInPhase = req;           
            cap = INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            USBEP0TxCnt = 0x01;
            pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B = cap;
            usb_ep0_in();
            break;
            //case GET_MIN_CMD:
            //case GET_MAX_CMD:
            //case GET_RES_CMD:
            //case GET_LEN_CMD:
            //case GET_DEF_CMD:
        default:
            // un-support
            usb_vc_stall(CONTROL_INVALID_REQUEST);
            break;
        }        
        break;
#endif  // #if (USING_STILL_METHOD_1 == 0)
#if 0
    case VS_CONTROL_UNDEFINED:
    case VS_STREAM_ERROR_CODE_CONTROL:
    case VS_GENERATE_KEY_FRAME_CONTROL:
    case VS_UPDATE_FRAME_SEGMENT_CONTROL:
    case VS_SYNCH_DELAY_CONTROL:
#endif
    default:
        // un-support
        usb_vc_stall(CONTROL_INVALID_CONTROL);
        break;
    }
}
#endif

void usb_vc_req_proc(MMP_UBYTE req)
{
    MMP_UBYTE id;

    id = (UsbRequestPayload_wIndex >> 8);
#if 0
    RTNA_DBG_Str3("VC.Req:");
    RTNA_DBG_Byte3(req);
    RTNA_DBG_Str3(",");
 
    RTNA_DBG_Str3("VC.Id:");
    RTNA_DBG_Byte3(id);
    RTNA_DBG_Str3("\r\n");    
#endif
    if(id == 0x00){
        //if Hbyte of wIndex is 0 -> interface control request otherwise are Terminal ID or Unit ID
        if((UsbRequestPayload_wIndex & 0xFF) == UVC_D1_STREAM_IF1_NO){
            gbProbeCommitCamera = 0;
            usb_vc_vsi_cs(req);
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D1_CTL_IF_NO){
            usb_vc_vci_cs(req);
#if (SUPPORT_DUAL_DEVICE||SUPPORT_SWITCH_CAMERA)
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D2_STREAM_IF1_NO){
            gbProbeCommitCamera = 1;
            usb_vc_vsi_cs(req);
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D2_CTL_IF_NO){
            usb_vc_vci_cs(req);
#endif
        }
        else{
            usb_vc_stall_rx(CONTROL_INVALID_UNIT);
        }
    }
    else if(id == UVC_IT_ID){
        usb_vc_ct_cs(req);
    } 
#if 0    
    else if(id == gbVCOTID) {
    }
#endif
#if SUPPORT_SU
    else if(id == gbVCSUID){
        usb_vc_su_cs(req);
    }
#endif          
    else if(id == UVC_PU_ID){
        usb_vc_pu_cs(req);
    }
#if (SECS_VER > 0)
    else if(id == gbVCEU0ID){
        usb_vc_eu0_cs(req);
    } 
#endif
#if SKYPE_UVC_H264
    else if(id == gbVCEU3ID){
        usb_vc_eu3_cs(req);
    } 
#endif
    else if(id == gbVCEU1ID){
        usb_vc_eu1_cs(req);
    }
    else if(id == gbVCEU2ID){
        usb_vc_eu2_cs(req);
    }
    else{
        usb_vc_stall_rx(CONTROL_INVALID_UNIT);
    }
}

void usb_vc_vci_cs_out(void)
{
    MMP_UBYTE cs;

    cs = (UsbRequestPayload_wValue >> 8);

    switch(cs){
#if 0
case VC_VIDEO_POWER_MODE_CONTROL:
    // under coding
    //usb_vc_stallRx(CONTROL_UNKNOWN);
    usb_vc_stall_rx(CONTROL_INVALID_CONTROL);//Truman@120710 I think here should use invalid control
    break;
case VC_REQUEST_ERROR_CODE_CONTROL:
    // un-support
    //usb_vc_stallRx(CONTROL_INVALID_REQUEST);
    usb_vc_stall_rx(CONTROL_INVALID_CONTROL);//Truman@120710 I think here should use invalid control
    break;
#endif
        //case VC_CONTROL_UNDEFINED:
        //case VC_RESERVED:
    default:
        // impossible flow
        usb_vc_stall_rx(CONTROL_INVALID_CONTROL);//Truman@120710 I think here should use invalid control
        break;
    }
}

#if SUPPORT_SU
void usb_vc_su_cs_out(void)
{
    MMP_UBYTE cs,tmp;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;   

    cs = (UsbRequestPayload_wValue >> 8);

    switch(cs){
    case SU_INPUT_SELECT_CONTROL:
        USBInPhase = SET_CUR_CMD;
        USBOutData = 0;           
        tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        if(tmp != 1){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            usb_ep0_null_in();
        }
        break;
        //case SU_CONTROL_UNDEFINED:
    default:
        // impossible flow
        break;
    }
}
#endif

void usb_vc_ct_cs_out(void)
{
    MMP_UBYTE cs,len;
#if (CUSTOMER != ASU)||((CUSTOMER == ASU)&&(MODEL == 0))
    MMP_LONG pan,tilt;
#endif
    MMP_USHORT tmp2;
#if 1//USE_CS_OUT_RANGE_CHK == 0
    MMP_UBYTE tmp;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
#endif
    MMP_ULONG tmp4;

    cs = (UsbRequestPayload_wValue >> 8);
    len = UsbRequestPayload_wLength;

    switch(cs){
    case CT_AE_MODE_CONTROL:
#if 0//USE_CS_OUT_RANGE_CHK // AE_MODE value is discrete value, should not use usb_vc_cmd_get_simple_value to check
            if (usb_vc_cmd_get_simple_value(&CT_AE_MODE_CFG, &gbAE, "CtAeMode")) {
                return;
            }
#else
           USBOutData = 0;           
           tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
           if((tmp != 4) && (tmp != 2) && (tmp != 1)){
                // un-support
            #if 0
                RTNA_DBG_Str3("  CT_AE_MODE_CONTROL stall\r\n");
            #endif
               usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
               RETURN_IF_USE_RANGE_CHK;
               break;
           }
#endif
        else{
#if 0//USE_CS_OUT_RANGE_CHK
               if (gbAE == 3) {
                   usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
                   return;
               }
#else
              gbAE = tmp;
#endif
            dbg_printf(3, " gbAE = %d\r\n", gbAE);

            if(gbAE == AEC_DEF){
                USB_EnableAE(PCAM_NONBLOCKING, 1);
                //ISP_IF_3A_SetSwitch(ISP_3A_ALGO_AE,1);
                //ISP_IF_3A_Control(ISP_3A_ENABLE);
                gbEVInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT |
                           INFO_AUTO_MODE_SUPPORT |
                           INFO_GET_SUPPORT |
                           INFO_SET_SUPPORT;
#if (CUSTOMER == PNS)
#if (SECS_VER > 20)//if H264 or SECS case, min fps =15
                if((gbCurH264Type == SKYPE_TX_STREAM) || (m_VideoFmt == MMPS_3GPRECD_VIDEO_FORMAT_H264)){
                    ISP_IF_AE_SetSysMode(0);
                    ISP_IF_AE_SetMinFPSx10(150);
                }
                else// other format, min fps = 1
                    #endif
                {
                    ISP_IF_AE_SetSysMode(1);
                    ISP_IF_AE_SetMinFPSx10(10);
                }
#endif
            }
            else{
                USB_EnableAE(PCAM_NONBLOCKING, 0);
                //ISP_IF_3A_SetSwitch(ISP_3A_ALGO_AE,0);
                //ISP_IF_3A_Control(ISP_3A_DISABLE);
                gbEVInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_GET_SUPPORT | INFO_SET_SUPPORT;
            }    
            if(gbAE != gblastAE)
                gbUpdAE = 1;
            gblastAE = gbAE;
        }

#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;

    case CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&CT_EXPOSURE_TIME_ABS_CFG, &tmp4, "CtExpTimeAbs")){
            return;
        }
#else
        USBOutData = 0;
        usb_vc_get_ep0_data((MMP_UBYTE *) &tmp4);
        //tmp4 = (MMP_ULONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        //tmp4 |= (MMP_ULONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B<<8;
        //tmp4 |= (MMP_ULONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B<<16;
        //tmp4 |= (MMP_ULONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B<<24;
        if(gbAE == AEC_DEF){
#if 0
    RTNA_DBG_Str3("  CT_EXPOSURE_TIME_ABSOLUTE_CONTROL stall\r\n");
#endif
            usb_vc_stall_rx(CONTROL_WRONG_STATE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        if((tmp4 > EPV_MAX) || (tmp4 < EPV_MIN)){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
#endif
        else{
            if(gbAE == AEC_DEF){
                usb_vc_stall_rx(CONTROL_WRONG_STATE);
                return;
            }
            gsEV = tmp4;
#if (CUSTOMER == PNS)
#if (SECS_VER > 20)
            if(!((gbCurH264Type == SKYPE_TX_STREAM) || (m_VideoFmt == MMPS_3GPRECD_VIDEO_FORMAT_H264)))
                            #endif
                switch(gsEV){
                case 100:
                    gsEV *= 1.04;
                    break;
                case 156:
                    gsEV *= 2.08;
                    break;
                case 312:
                    gsEV *= 3.12;
                    break;
                case 625:
                    gsEV *= 4.16;
                    break;
                case 1250:
                    gsEV *= 5.20;
                    break;
                case 2000:
                    gsEV *= 6.25;
                    break;
                }
#endif
            // to do here
            //ISP_IF_SNR_SetShutter((gsEV * 2), ISP_IF_AE_GetVsync());
            USB_SetAEExposureValue(PCAM_NONBLOCKING, gsEV);
            dbg_printf(3, " gsEV = %d\r\n", gsEV);
        }
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;

    case CT_FOCUS_ABSOLUTE_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&CT_FOCUS_ABS_CFG, &gsAFocus, "CTFocusABS")){
            return;
        }
#else
        USBOutData = 0;
        //tmp2 = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 += pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B * 0x100;

        if((tmp2 < AAF_MIN) || (tmp2 > AAF_MAX)){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        } 
#endif
        else{
#if USE_CS_OUT_RANGE_CHK == 0
            gsAFocus = tmp2;
#endif
            USB_SetLensPosition(PCAM_OVERWR, gsAFocus);
#if 0
            RTNA_DBG_Str(3, "  gsAFocus = ");       
            RTNA_DBG_Short(3, gsAFocus);
            RTNA_DBG_Str(3, "\r\n");
#endif            
        }             
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;

    case CT_FOCUS_AUTO_CONTROL:
         {
            //            RTNA_DBG_Str(3, "  == CT_FOCUS_AUTO_CONTROL =  ");       
            //            RTNA_DBG_Byte(3, tmp);
            //            RTNA_DBG_Str(3, "\r\n");
#if USE_CS_OUT_RANGE_CHK
            if(usb_vc_cmd_get_simple_value(&CT_FOCUS_AUTO_CFG, &gbAutoFocus, "CTFocusAuto")){
                return;
            }
#else
            MMP_BOOL tmp;
            USBOutData = 0;           
            tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;

            if(tmp<AUTOAF_MIN || tmp>AUTOAF_MAX){
                // un-support
                UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
                gbVCERRCode = CONTROL_OUT_OF_RANGE;
                break;
            }
#endif
            else{
#if USE_CS_OUT_RANGE_CHK == 0
                gbAutoFocus = tmp;
#endif
                if(gbAutoFocus){
                    USB_EnableAF(PCAM_NONBLOCKING, gbAutoFocus);
                }
#if 0                
                RTNA_DBG_Str(3, "  gbAutoFocus = ");       
                RTNA_DBG_Short(3, gbAutoFocus);
                RTNA_DBG_Str(3, "\r\n");
#endif            
            }            
#if USE_CS_OUT_RANGE_CHK == 0
            USBInPhase = SET_CUR_CMD;
            usb_ep0_null_in();
#endif
        }
        break; 
#if SUPPORT_DIGITAL_ZOOM
    case CT_ZOOM_ABSOLUTE_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&CT_ZOOM_ABS_CFG, &tmp2, "CTZoomABS")){
            return;
        }
#else
        USBOutData = 0;
        USB_GET_FIFO_DATA(MMPF_USB_EP0, len, (MMP_UBYTE *) &tmp2, sizeof(tmp2));

        if(tmp2<ZOM_MIN || tmp2>ZOM_MAX){
            // un-support
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_OUT_OF_RANGE;                    
            break;
        }
#endif
        else{
            // Enable Async Mode
            if(CT_ZOOM_ABS_CFG.bInfoCap & INFO_ASYNC_CONTROL_SUPPORT){
                USB_SetAsyncVideoControl(UVC_IT_ID, CT_ZOOM_ABSOLUTE_CONTROL, 0, 2);
            }
            USB_SetDigitalZoom(PCAM_OVERWR /*PCAM_NONBLOCKING*/, 2, gsZoom, tmp2, ZOM_MAX); // 2->Auto
            gsZoom = tmp2 ;

            //dbg_printf(3, "gsZoom = %x\r\n", gsZoom);
        }      
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        // while(1);
        break;
#endif        
#if SUPPORT_DIGITAL_PAN || (UVC_IT_BITMAP & (1 << 11))
    case CT_PANTILT_ABSOLUTE_CONTROL:
        USBOutData = 0;
#if ((CUSTOMER == ASU) && (MODEL == 1))
        usb_vc_get_ep0_data((MMP_UBYTE *) CT_PANTILT_ABS_CFG.dwCurVal);
        if(gPCCamCurRes != NULL){
            FOCUSED_RECT * const pFR = (FOCUSED_RECT *) (VC_XU_ASU_FOCUS_RECT_CFG.dwCurVal);
            MMP_ULONG x, y;
            x = ((MMP_ULONG *) CT_PANTILT_ABS_CFG.dwCurVal)[0] / 360;
            y = ((MMP_ULONG *) CT_PANTILT_ABS_CFG.dwCurVal)[1] / 360;

            //current application only, now the app set x,0 and 0,y instead of x,y
            if(x){
                pFR->wLeft = x - (gPCCamCurRes->res_w / 12);
                if(pFR->wLeft > 0x8000){
                    // < 0
                    pFR->wLeft = 0;
                }
                pFR->wRight = x + (gPCCamCurRes->res_w / 12);
                if(pFR->wRight > gPCCamCurRes->res_w){
                    // < 0
                    pFR->wRight = gPCCamCurRes->res_w;
                }
            }

#if 1            
            //temp process to fix x, y coordinate
             {
                pFR->wTop = y - (gPCCamCurRes->res_h / 12);
                if(pFR->wTop > 0x8000){
                    // < 0
                    pFR->wTop = 0;
                }
                pFR->wBottom = y + (gPCCamCurRes->res_h / 12);
                if(pFR->wBottom > gPCCamCurRes->res_h){
                    // < 0
                    pFR->wBottom = gPCCamCurRes->res_h;
                }
                if(y == 0){
                    pFR->wBottom += (gPCCamCurRes->res_h / 12);
                }
            }
#else
            //original process
            if(y){
                pFR->wTop = y - (gPCCamCurRes->res_h / 12);
                if(pFR->wTop > 0x8000){
                    // < 0
                    pFR->wTop = 0;
                }
                pFR->wBottom = y + (gPCCamCurRes->res_h / 12);
                if(pFR->wBottom > gPCCamCurRes->res_h){
                    // < 0
                    pFR->wBottom = gPCCamCurRes->res_h;
                }
            }
#endif
            dbg_printf(1, "res:%dx%d ", gPCCamCurRes->res_w, gPCCamCurRes->res_h);
            dbg_printf(1, "center:%d,%d ", x, y);
            dbg_printf(1, "rect:%d,%d-%dx%d,", pFR->wLeft, pFR->wTop, pFR->wRight, pFR->wBottom);
        }

        xu_asu_config_twindow();

        //for current app only, force to use TAF
        //VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE)1;
        //dbg_printf(1, " AF");
        //xu_asu_config_taf();
#elif ((CUSTOMER == ASU) && (MODEL == 2))
        usb_vc_get_ep0_data((MMP_UBYTE*)CT_PANTILT_ABS_CFG.dwCurVal);
        {
            MMP_ULONG n_ev, n_iso;
            n_ev = ((MMP_ULONG *) CT_PANTILT_ABS_CFG.dwCurVal)[0] / 3600;
            n_iso = ((MMP_ULONG *) CT_PANTILT_ABS_CFG.dwCurVal)[1] / 360;

            //current application only, ev input -21~21 ==> normalize ==> 0~20
            if((n_ev >= -21) && (n_ev <= 21)){
                MMP_SHORT n_ev_val = (MMP_SHORT) (((20.0 * (n_ev + 21)) / 42)) ;
                dbg_printf(1, "[OK]EV:%d.\r\n ", n_ev);
                ISP_IF_AE_SetEV(n_ev_val);
            }
            else{
                dbg_printf(1, "[!]EV:%d, out of range!:%d\r\n", n_ev);
            }

            //current application only, iso input 5~80 ==> normalize ==> 50~800
            if((n_iso == 50) || (n_iso == 100) || (n_iso == 200) || (n_iso == 400) || (n_iso == 800)){
                dbg_printf(1, "[OK]ISO:%d.\r\n ", n_iso);
                ISP_IF_AE_SetISO(n_iso);
            }
            else{
                dbg_printf(1, "[!]ISO:%d, out of range!:%d\r\n", n_iso);
            }
        }

#else
#if 0 
pan  = (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
pan |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8 ;
pan |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 16 ;
pan |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 24 ;

tilt  = (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
tilt |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8 ;
tilt |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 16 ;
tilt |= (MMP_LONG)pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 24 ;

#else
if(len < 4 ) {
    USB_GET_FIFO_DATA(MMPF_USB_EP0, len , (MMP_UBYTE *)&pan, sizeof(pan) );
    tilt = 0 ;
} else {
    USB_GET_FIFO_DATA(MMPF_USB_EP0, 4 , (MMP_UBYTE *)&pan, sizeof(pan) );
    len = len - 4 ;
    USB_GET_FIFO_DATA(MMPF_USB_EP0 ,len , (MMP_UBYTE *)&tilt, sizeof(tilt) );
}
#endif

        //pan = 0;
        //
        // NOTES:
        //   
        // It looks like Windows-XP has a bug, when adjust Tilt value.
        // Pan value will be garbage.
        //
        if(pan < PAN_MIN || pan > PAN_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        } 

        if(tilt < TILT_MIN || tilt > TILT_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }

        if(1){
            // Enable Async Mode
            if(CT_PANTILT_ABS_CFG.bInfoCap & INFO_ASYNC_CONTROL_SUPPORT){
                USB_SetAsyncVideoControl(UVC_IT_ID, CT_PANTILT_ABSOLUTE_CONTROL, 0, 8);
            }    
            USB_SetDigitalPanTilt(PCAM_OVERWR, /*PCAM_NONBLOCKING*/glPan, pan, glTilt, tilt,
                                  (PAN_MAX - PAN_MIN) / PANTILT_RES);
#if 0                
            RTNA_DBG_Str(3, "\r\n");
            RTNA_DBG_Str(3, "\r\n");
            RTNA_DBG_Str(3, "  [glPan -> pan] : ");       
            RTNA_DBG_Short(3, glPan);
            RTNA_DBG_Str(3, " -> ");       
            RTNA_DBG_Short(3, pan);
            RTNA_DBG_Str(3, ",  [glTilt -> tilt] : ");       
            RTNA_DBG_Short(3, glTilt);
            RTNA_DBG_Str(3, " -> ");       
            RTNA_DBG_Short(3, tilt);
            RTNA_DBG_Str(3, "\r\n");
#endif            
            glPan = pan ; 
            glTilt = tilt;
        }
#endif
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
#endif        
#if UVC_IT_BITMAP & (1 << 12) && (CUSTOMER == ASU)
    case CT_PANTILT_RELATIVE_CONTROL:
         {
            CMD_VALUE tmp;
            USBOutData = 0;
            usb_vc_get_ep0_data((MMP_UBYTE *) &CT_PANTILT_RELATIVE_CFG.dwCurVal);
            tmp = VC_XU_ASU_AE_LOCK_CFG.dwCurVal;
            VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) (((MMP_ULONG) CT_PANTILT_RELATIVE_CFG.dwCurVal) >> 24);
            if(tmp != VC_XU_ASU_AE_LOCK_CFG.dwCurVal){
                xu_asu_config_tae();
            }

            tmp = VC_XU_ASU_AF_LOCK_CFG.dwCurVal;
            VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE)
                                             ((((MMP_ULONG) CT_PANTILT_RELATIVE_CFG.dwCurVal) >> 8) & 0xFF);
            if(tmp != VC_XU_ASU_AE_LOCK_CFG.dwCurVal){
                xu_asu_config_taf();
            }
#if USE_CS_OUT_RANGE_CHK == 0
            USBInPhase = SET_CUR_CMD;
            usb_ep0_null_in();
#endif
        }
        break;
#endif
#if UVC_IT_BITMAP & (1 << 13) && (CUSTOMER == ASU)
    case CT_ROLL_ABSOLUTE_CONTROL:
        USBOutData = 0;
#if (MODEL == 2)//(CUSTOMER == ASU)
         {
            MMP_UBYTE n_imageeffect, n_scenemode, n_witebalance;

            usb_vc_get_ep0_data((MMP_UBYTE *) &CT_ROLL_ABS_CFG.dwCurVal);
            n_imageeffect = (((MMP_USHORT *) CT_ROLL_ABS_CFG.dwCurVal)[0]) & 0x003F; //0~5
            n_scenemode = ((((MMP_USHORT *) CT_ROLL_ABS_CFG.dwCurVal)[0]) & 0x07C0) >> 6; //6~10
            n_witebalance = ((((MMP_USHORT *) CT_ROLL_ABS_CFG.dwCurVal)[0]) & 0xF800) >> 11; //11~15

            //current application only, effect input 0~4 ==> map to ==> (None/Aqua/Negative/Sepia/Grayscale)
            if(n_imageeffect < 5){
                MMP_SHORT n_imageeffect_val;

                dbg_printf(1, "[OK]IMAGE_EFFECT:%d.\r\n ", n_imageeffect);
                switch(n_imageeffect){
                case 0:
                    n_imageeffect_val = 0; break;
                case 1:
                    n_imageeffect_val = 5; break;
                case 2:
                    n_imageeffect_val = 3; break;
                case 3:
                    n_imageeffect_val = 2; break;
                default:
                case 4:
                    n_imageeffect_val = 1; break;
                }
                ISP_IF_F_SetImageEffect(n_imageeffect_val);
            }
            else{
                dbg_printf(1, "[!]IMAGE_EFFECT:%d, out of range!:%d\r\n", n_imageeffect);
            }

            //current application only, scene input 0~8 ==> map to ==> (Auto/InDoor/Landscape/Night/Portrait/Snow/Sunset/Backlight/Vivid)
            if(n_scenemode < 9){
                MMP_SHORT n_scenemode_val;

                dbg_printf(1, "[OK]SCENE_MODE:%d.\r\n ", n_scenemode);
                switch(n_imageeffect){
                case 0:
                    n_scenemode_val = 0; break;
                case 1:
                    n_scenemode_val = 11; break;
                case 2:
                    n_scenemode_val = 2; break;
                case 3:
                    n_scenemode_val = 7; break;
                case 4:
                    n_scenemode_val = 1; break;
                case 5:
                    n_scenemode_val = 12; break;
                case 6:
                    n_scenemode_val = 4; break;
                case 7:
                    n_scenemode_val = 8; break;
                default:
                case 8:
                    n_scenemode_val = 10; break;
                }
                ISP_IF_F_SetScene(n_scenemode_val);
            }
            else{
                dbg_printf(1, "[!]SCENE_MODE:%d, out of range!:%d\r\n", n_scenemode);
            }

            //current application only, WB input 0~4 ==> map to ==> (Daylight/Cloudy/Shade/Fluorescent/Tungsten) (6500/7500/7000/3400/3200)
            if(n_witebalance < 5){
                MMP_SHORT n_witebalance_val;

                dbg_printf(1, "[OK]WHITE_BALANCE:%d.\r\n ", n_witebalance);
                switch(n_imageeffect){
                case 0:
                    n_witebalance_val = 6500; break;
                case 1:
                    n_witebalance_val = 7500; break;
                case 2:
                    n_witebalance_val = 7000; break;
                case 3:
                    n_witebalance_val = 3400; break;
                default:
                case 4:
                    n_witebalance_val = 3200; break;
                }
                ISP_IF_AWB_SetColorTemp(n_witebalance_val);
            }
            else{
                dbg_printf(1, "[!]WHITE_BALANCE:%d, out of range!:%d\r\n", n_witebalance);
            }
        }
#else
         {
            //TODO: This always does TAF & TAE. It might not necessary to do it every time. Try to do it only when it is different then previous time.
#if (ASU_CAMERA_APP_VERSION > 29)
            MMP_USHORT nRollWriteCtl;
            MMP_UBYTE n_imageeffect, n_scenemode, n_iso;

            //usb_vc_get_ep0_data((MMP_UBYTE*)&CT_ROLL_ABS_CFG.dwCurVal);
            //nRollWriteCtl = ((MMP_USHORT *)CT_ROLL_ABS_CFG.dwCurVal)[0];
            usb_vc_get_ep0_data((MMP_UBYTE *) &nRollWriteCtl);

            VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) (nRollWriteCtl & 0x03);
            VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) ((nRollWriteCtl & 0x04) >> 2);
            n_scenemode = ((nRollWriteCtl & 0x78) >> 3); //3~6
            n_imageeffect = ((nRollWriteCtl & 0x1C0) >> 10); //10~12
            n_iso = ((nRollWriteCtl & 0xE000) >> 10); //13~15

            xu_asu_config_taf();
            xu_asu_config_tae();

            //current application only, scene input 0~8 ==> map to ==> (Auto/InDoor/Landscape/Night/Portrait/Snow/Sunset/Backlight/Vivid)
            if(n_scenemode < 9){
                MMP_SHORT n_scenemode_val;

                dbg_printf(1, "[OK]SCENE_MODE:%d.\r\n ", n_scenemode);
                switch(n_imageeffect){
                case 1:
                    n_scenemode_val = 11; break;
                case 2:
                    n_scenemode_val = 2; break;
                case 3:
                    n_scenemode_val = 7; break;
                case 4:
                    n_scenemode_val = 1; break;
                case 5:
                    n_scenemode_val = 12; break;
                case 6:
                    n_scenemode_val = 4; break;
                case 7:
                    n_scenemode_val = 8; break;
                case 8:
                    n_scenemode_val = 10; break;
                default:
                case 0:
                    n_scenemode_val = 0; break;
                }
                ISP_IF_F_SetScene(n_scenemode_val);
            }
            else{
                dbg_printf(1, "[!]SCENE_MODE:%d, out of range!:%d\r\n", n_scenemode);
            }

            //current application only, effect input 0~4 ==> map to ==> (None/Aqua/Negative/Sepia/Grayscale)
            if (n_imageeffect<5)
            {
                MMP_SHORT n_imageeffect_val;

                dbg_printf(1, "[OK]IMAGE_EFFECT:%d.\r\n ", n_imageeffect);
                switch(n_imageeffect){
                case 1:
                    n_imageeffect_val = 5; break;
                case 2:
                    n_imageeffect_val = 3; break;
                case 3:
                    n_imageeffect_val = 2; break;
                case 4:
                    n_imageeffect_val = 1; break;
                default:
                case 0:
                    n_imageeffect_val = 0; break;
                }
                ISP_IF_F_SetImageEffect(n_imageeffect_val);
            }
            else{
                dbg_printf(1, "[!]IMAGE_EFFECT:%d, out of range!:%d\r\n", n_imageeffect);
            }

            //current application only, iso input 0~5 ==> map to ==> (Auto/50/100/200/400/800)
            if(n_iso < 6){
                MMP_ULONG n_iso_val;

                dbg_printf(1, "[OK]ISO:%d.\r\n ", n_iso);
                switch(n_iso_val){
                case 1:
                    n_iso_val = 50; break;
                case 2:
                    n_iso_val = 100; break;
                case 3:
                    n_iso_val = 200; break;
                case 4:
                    n_iso_val = 400; break;
                case 5:
                    n_iso_val = 800; break;
                default:
                case 0:
                    n_iso_val = 0; break;
                }
                ISP_IF_AE_SetISO(n_iso_val);
            }
            else{
                dbg_printf(1, "[!]ISO:%d, out of range!:%d\r\n", n_iso);
            }


#elif (ASU_CAMERA_APP_VERSION > 23)
            //lockdown TAE/TAF process
            MMP_USHORT nRollWriteCtl;

            usb_vc_get_ep0_data((MMP_UBYTE *) &nRollWriteCtl);

            VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) ((nRollWriteCtl & 0x04) >> 2);
            xu_asu_config_tae();

            if((m_asuValidRect) &&
               ((MMP_UBYTE) (MMP_ULONG) VC_XU_ASU_AE_LOCK_CFG.dwCurVal == 1) &&
               ((MMP_UBYTE) (MMP_ULONG) VC_XU_ASU_AF_LOCK_CFG.dwCurVal == 1)){
                m_tTAEEnableCount = 30;//delay 30 frame count for AE first
            }

            VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) (nRollWriteCtl & 0x03);
            xu_asu_config_taf();
#else
            //original process
            MMP_UBYTE nRollWriteCtl;

            usb_vc_get_ep0_data((MMP_UBYTE *) &nRollWriteCtl);

            if((nRollWriteCtl) & 1){
                VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) 1;
            }
            else{
                VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) 0;
            }
            xu_asu_config_taf();
            if(VC_XU_ASU_LAST_ERROR_CFG.dwCurVal != (CMD_VALUE) ASU_ERR_NONE){
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 0x3;//FAIL
            }
            else{
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 0x0;
            }

            if((nRollWriteCtl) & 4){
                VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) 1;
            }
            else{
                VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) 0;
            }
            xu_asu_config_tae();
            if(VC_XU_ASU_LAST_ERROR_CFG.dwCurVal != (CMD_VALUE) ASU_ERR_NONE){
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 0x3;//FAIL
            }
            else{
                CT_ROLL_ABS_CFG.dwCurVal = (CMD_VALUE) 0x0;
            }

            if(CT_ROLL_ABS_CFG.dwCurVal != (CMD_VALUE) 0x03){
                CT_ROLL_ABS_CFG.dwCurVal = 0/*idle*/;/*TODO: make it to busy and reached status later if
                                                             Asus requested this or using continuous AF. */
            }
#endif
        }
#endif
        break;
#endif
#if UVC_IT_BITMAP & (1 << 21)
    case CT_REGION_OF_INTEREST:
         {
            //warning: this is not full CT_ROI function. Now it is for TAF,TAE only
            CMD_VALUE tmp;
            FOCUSED_RECT * const pFR = (FOCUSED_RECT *) (VC_XU_ASU_FOCUS_RECT_CFG.dwCurVal);
            CT_ROI * const pCtRoi = (CT_ROI *) (CT_ROI_CFG.dwCurVal);

            USBOutData = 0;
            usb_vc_get_ep0_data((MMP_UBYTE *) &CT_ROI_CFG.dwCurVal);

            pFR->wLeft = pCtRoi->wROI_Left;
            pFR->wRight = pCtRoi->wROI_Right;
            pFR->wTop = pCtRoi->wROI_Right;
            pFR->wBottom = pCtRoi->wROI_Bottom;
            xu_asu_config_twindow();

            if(m_asuValidRect == 0){
                xu_asu_set_err(ASU_ERR_NOT_ALLOWED);
                break;
            }

            //it does not check the range of CT_WINDOW either.
            tmp = VC_XU_ASU_AE_LOCK_CFG.dwCurVal;
            if(pCtRoi->bmAutoControls & CT_ROI_AE){
                VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) 1;
            }
            else{
                VC_XU_ASU_AE_LOCK_CFG.dwCurVal = (CMD_VALUE) 0;
            }
            if(tmp != VC_XU_ASU_AE_LOCK_CFG.dwCurVal){
                xu_asu_config_tae();
            }

            tmp = VC_XU_ASU_AF_LOCK_CFG.dwCurVal;
            if(pCtRoi->bmAutoControls & CT_ROI_AF){
                VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) 1;
            }
            else{
                VC_XU_ASU_AF_LOCK_CFG.dwCurVal = (CMD_VALUE) 0;
            }
            if(tmp != VC_XU_ASU_AE_LOCK_CFG.dwCurVal){
                xu_asu_config_taf();
            }
#if USE_CS_OUT_RANGE_CHK == 0
            USBInPhase = SET_CUR_CMD;
            usb_ep0_null_in();
#endif
        }
        break;
#endif
#if 0
    case CT_CONTROL_UNDEFINED:
    case CT_SCANNING_MODE_CONTROL:
    case CT_AE_PRIORITY_CONTROL:
    case CT_EXPOSURE_TIME_RELATIVE_CONTROL:
    case CT_FOCUS_RELATIVE_CONTROL:
        // case CT_FOCUS_AUTO_CONTROL:
    case CT_IRIS_ABSOLUTE_CONTROL:
    case CT_IRIS_RELATIVE_CONTROL:
    case CT_ZOOM_RELATIVE_CONTROL:
    case CT_PANTILT_RELATIVE_CONTROL:
    case CT_ROLL_ABSOLUTE_CONTROL:
    case CT_ROLL_RELATIVE_CONTROL:
    case CT_PRIVACY_CONTROL:
#endif
    default:
        // impossible flow
        usb_vc_stall_rx(CONTROL_INVALID_CONTROL);
        return;
        break;
    }
#if USE_CS_OUT_RANGE_CHK
    USBInPhase = SET_CUR_CMD;
    usb_ep0_null_in();
#endif
}

void usb_vc_init_sensor_param(void)
{
#if 1 // test for suspend/wakeup preview
    // sean@201_08_24, change to API call for suspend/wake up preview test
    //gbZoom;
#if SUPPORT_PU_DEFAULT
    extern MMP_ERR USB_ReadPUFlash(void);
    extern MMP_USHORT pu_flash_data[10];
    MMP_ULONG PU_Status, preview_tmp;
    PU_Status = USB_ReadPUFlash();
    if(PU_Status == 0) {
        preview_tmp = m_bVidRecdPreviewStatus;
        m_bVidRecdPreviewStatus = MMP_TRUE;
    
        gsBrightness = pu_flash_data[0];
        gsContrast   = pu_flash_data[1];
        gsHue        = pu_flash_data[2];
        gsSaturation = pu_flash_data[3];
        gsSharpness  = pu_flash_data[4];
        gsGamma      = pu_flash_data[5];
        gbAWB        = pu_flash_data[6];
        gsTemper     = pu_flash_data[7];
        gsBacklight  = pu_flash_data[8];
        gsGain       = pu_flash_data[9];
    
        USB_SetPowerLineFreq(PCAM_API, gbBandFilter);

        USB_SetBrightness(PCAM_API,gsBrightness);
        USB_SetContrast(PCAM_API,gsContrast);
        if(gsHue != HUE_DEF){
            USB_SetHue(PCAM_API,gsHue);
        }
        USB_SetSaturation(PCAM_API,gsSaturation);
        USB_SetSharpness(PCAM_API,gsSharpness);
        if(gsGamma != GAM_DEF){
            USB_SetGamma(PCAM_API,gsGamma);
        }
        if(gbAWB != AWB_DEF){
            USB_SetAWBMode(PCAM_API,gbAWB);
            gbTemperInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_SET_SUPPORT | INFO_GET_SUPPORT;
        }
        if((gbAWB != AWB_DEF) && (gsTemper != WBT_DEF)){
            USB_SetAWBTemp(PCAM_API,gsTemper);
        }
        if(gsBacklight != BLC_DEF){
            USB_SetBacklight(PCAM_API,gsBacklight);
        }
        if((gbAE != AEC_DEF) && (gsGain != GAIN_DEF)){
            USB_SetGain(PCAM_API,gsGain);
        }

        if(gbAE != AEC_DEF){
            USB_EnableAE(PCAM_API, 0);
            gbEVInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT| INFO_GET_SUPPORT | INFO_SET_SUPPORT;
        }
        if((gbAE != AEC_DEF) && (gsEV != EPV_DEF)){
            USB_SetAEExposureValue(PCAM_API,gsEV);
            USB_SetGain(PCAM_API,GAIN_DEF);
        }

        m_bVidRecdPreviewStatus = preview_tmp;
    }
    else
#endif
    {
        USB_SetPowerLineFreq(PCAM_API, gbBandFilter);
        //gsBacklight;
        if(gsBacklight != BLC_DEF){    
            USB_SetBacklight(PCAM_API,gsBacklight);
        }
        USB_SetSaturation(PCAM_API,gsSaturation);
        USB_SetContrast(PCAM_API,gsContrast);
        USB_SetBrightness(PCAM_API,gsBrightness);
        USB_SetSharpness(PCAM_API,gsSharpness);
        //gsHue;
        if(gsHue != HUE_DEF){
            USB_SetHue(PCAM_API,gsHue);
        }
        //gsGamma;
        if(gsGamma != GAM_DEF){
            USB_SetGamma(PCAM_API,gsGamma);         
        }
        //gbTemperInfo;
        //gbAWB;
        //gblastAWB;
        if(gbAWB != AWB_DEF){
            USB_SetAWBMode(PCAM_API,gbAWB); // ooxx
            gbTemperInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_SET_SUPPORT | INFO_GET_SUPPORT;
        }
        //gsTemper;
        if((gbAWB != AWB_DEF) && (gsTemper != WBT_DEF)){
            USB_SetAWBTemp(PCAM_API,gsTemper);
        }

        //gbEVInfo;
        //gbAE;
        //gblastAE;
        if(gbAE != AEC_DEF){
            USB_EnableAE(PCAM_API, 0);  // disable AE
            gbEVInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT| INFO_GET_SUPPORT | INFO_SET_SUPPORT;
        }
        //gsEV;
        if((gbAE != AEC_DEF) && (gsEV != EPV_DEF)){
            USB_SetAEExposureValue(PCAM_API,gsEV);
            USB_SetGain(PCAM_API,GAIN_DEF);
        }
        //gsGain
        if((gbAE != AEC_DEF) && (gsGain != GAIN_DEF)){
            USB_SetGain(PCAM_API,gsGain);
        }

#if (SUPPORT_MP4) || (SUPPORT_MTS)
        if(MMPF_VIDMGR_GetMtsMuxModeEnable() || MMPF_VIDMGR_GetMP4Enable()){    
            //ISP_IF_AE_SetFPS(30);  // keep frame rate as constant //LAB
        }
#endif

        #if (CUSTOMER == ASU)
            m_asuValidRect = 0;
            ISP_IF_AE_SetCustomWinMode(ISP_CUSTOM_WIN_MODE_OFF);
            ISP_IF_AF_SetCustomWinMode(ISP_CUSTOM_WIN_MODE_OFF);
        #endif
    }
#endif
}

#if (IQ_SETTING_LOAD_FROM_FLASH)
extern MMP_UBYTE IQ_Setting[IQ_SETTING_MAX_SIZE];
#endif

void usb_vc_pu_cs_out(void)
{
    MMP_UBYTE cs;
    MMP_USHORT tmp2;
#if USE_CS_OUT_RANGE_CHK == 0
    MMP_UBYTE tmp, len;
    MMP_SHORT  sTmp;
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;   
#endif

    cs = (UsbRequestPayload_wValue >> 8);
#if USE_CS_OUT_RANGE_CHK == 0
    len = UsbRequestPayload_wLength;
#endif

    switch(cs){
    case PU_BACKLIGHT_COMPENSATION_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_BACKLIGHT_CFG, &gsBacklight, "PuContrast")){
            return;
        }
        else{
            USB_SetBacklight(PCAM_NONBLOCKING, gsBacklight);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(tmp2 > BLC_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsBacklight = tmp2;
            // to do here
            USB_SetBacklight(PCAM_NONBLOCKING, gsBacklight);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_BRIGHTNESS_CONTROL:
        // under coding
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_BRIGHTNESS_CFG, &gsBrightness, "PuBri")){
            return;
        }
        else{
            USB_SetBrightness(PCAM_NONBLOCKING, gsBrightness);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(((short) tmp2) < BRI_MIN || ((short) tmp2) > BRI_MAX){
            // un-support
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_OUT_OF_RANGE;                    
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsBrightness = tmp2;
            // to do here
            USB_SetBrightness(PCAM_NONBLOCKING, gsBrightness);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_CONTRAST_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_CONTRAST_CFG, &gsContrast, "PuContrast")){
            return;
        }
        else{
            USB_SetContrast(PCAM_NONBLOCKING, gsContrast);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(tmp2 > CON_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsContrast = tmp2;
            // to do here
            USB_SetContrast(PCAM_NONBLOCKING, gsContrast);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_POWER_LINE_FREQUENCY_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_POWERLINEREQ_CFG, &gbBandFilter, "PuPowerHz")){
            return;
        }
        else{
#if (IQ_SETTING_LOAD_FROM_FLASH)
#if 0
    RTNA_DBG_Str3("  IQ_Setting[] = ");
    RTNA_DBG_Byte3(IQ_Setting[0]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[1]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[2]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[3]);
    RTNA_DBG_Str3("\r\n");
#endif
            if(IQ_Setting[BANDFILTER_OFFSET + 1] != gbBandFilter){
                MMPF_PCAM_Update_IQ_Setting(BANDFILTER_OFFSET, (MMP_ULONG) gbBandFilter, 1);
                IQ_Setting[BANDFILTER_OFFSET + 1] = gbBandFilter;
            }
#endif
            USB_SetPowerLineFreq(PCAM_NONBLOCKING, gbBandFilter);
            dbg_printf(3, "  BandFilter = %d\r\n", gbBandFilter);
        }
#else
        USBOutData = 0;           
        tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        if(tmp > 2){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gbBandFilter = tmp;
            // to do here
#if (IQ_SETTING_LOAD_FROM_FLASH)
#if 0
    RTNA_DBG_Str3("  IQ_Setting[] = ");
    RTNA_DBG_Byte3(IQ_Setting[0]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[1]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[2]);
    RTNA_DBG_Str3(" : ");
    RTNA_DBG_Byte3(IQ_Setting[3]);
    RTNA_DBG_Str3("\r\n");
#endif                
            if(IQ_Setting[BANDFILTER_OFFSET + 1] != gbBandFilter){
                MMPF_PCAM_Update_IQ_Setting(BANDFILTER_OFFSET, (MMP_ULONG) gbBandFilter, 1);  
                IQ_Setting[BANDFILTER_OFFSET + 1] = gbBandFilter;
            }
#endif
            USB_SetPowerLineFreq(PCAM_NONBLOCKING, gbBandFilter);

            RTNA_DBG_Str3("  gbBandFilter = ");
            RTNA_DBG_Byte3(gbBandFilter);
            RTNA_DBG_Str3("\r\n");
        }
#endif
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_HUE_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_HUE_CFG, &gsHue, "PuHue")){
            return;
        }
        else{
            USB_SetHue(PCAM_NONBLOCKING, gsHue);
        }
#else
        USBOutData = 0;
        tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;          
        sTmp = (MMP_SHORT) (pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B * 256 + tmp);
        if((sTmp > (MMP_SHORT) HUE_MAX) || (sTmp < (MMP_SHORT) HUE_MIN)){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsHue = sTmp;
            // to do here
            USB_SetHue(PCAM_NONBLOCKING, gsHue);
        }
#endif
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_SATURATION_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_SATURATION_CFG, &gsSaturation, "PuSaturation")){
            return;
        }
        else{
            USB_SetSaturation(PCAM_NONBLOCKING, gsSaturation);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(tmp2 > SAT_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsSaturation = tmp2;
            // to do here
            USB_SetSaturation(PCAM_NONBLOCKING, gsSaturation);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_SHARPNESS_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_SHARPNESS_CFG, &gsSharpness, "PuSharp")){
            return;
        }
        else{
            USB_SetSharpness(PCAM_NONBLOCKING, gsSharpness);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(tmp2 > SHA_MAX){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsSharpness = tmp2;
            // to do here
            USB_SetSharpness(PCAM_NONBLOCKING, gsSharpness);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
    case PU_GAMMA_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_GAMMA_CFG, &gsGamma, "PuGamma")){
            return;
        }
        else{
            USB_SetGamma(PCAM_NONBLOCKING, gsGamma);
        }
#else
        USBOutData = 0;           
        tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;          
        sTmp = (MMP_SHORT) (pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B * 256 + tmp);
        if((sTmp > (MMP_SHORT) GAM_MAX) || (sTmp < (MMP_SHORT) GAM_MIN)){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsGamma = sTmp;
            // to do here
            USB_SetGamma(PCAM_NONBLOCKING, gsGamma);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;

    case PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
        // under coding
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_WB_TEMP_CFG, &tmp2, "PuTemp")){
            return;
        }
        if(gbAWB){
            usb_vc_stall_rx(CONTROL_WRONG_STATE);//Truman: I think it should be CONTROL_WRONG_STATE rather than CONTROL_OUT_OF_RANGE
            return;
        }// Gason@ ooxx
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        if(gbAWB){
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_WRONG_STATE;
            RETURN_IF_USE_RANGE_CHK;
            break;
        }// Gason@ ooxx
        if(tmp2 > WBT_MAX || tmp2 < WBT_MIN){
            // un-support
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_OUT_OF_RANGE;
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
#endif
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsTemper = tmp2;
            USB_SetAWBTemp(PCAM_NONBLOCKING, gsTemper);
        }
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;

    case PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_WB_TEMP_AUTO_CFG, &gbAWB, "PuAwbAuto")){
            return;
        }
#else
        USBOutData = 0;           
        tmp = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        if(tmp > AWB_MAX || tmp < AWB_MIN){
            // un-support
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_OUT_OF_RANGE;
            RETURN_IF_USE_RANGE_CHK;
            break;
        }
#endif
        else{
#if USE_CS_OUT_RANGE_CHK == 0
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gbAWB = tmp;
#endif
            // to do here
            USB_SetAWBMode(PCAM_NONBLOCKING, gbAWB); // ooxx
            dbg_printf(3, "  gbAWB = %d\r\n");
        }

        if(gbAWB){
            gbTemperInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT |
                           INFO_AUTO_MODE_SUPPORT |
                           INFO_SET_SUPPORT |
                           INFO_GET_SUPPORT;
        }
        else{
            gbTemperInfo = INFO_AUTOUPDATE_CONTROL_SUPPORT | INFO_SET_SUPPORT | INFO_GET_SUPPORT;
        }
#if USE_CS_OUT_RANGE_CHK == 0
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif

        if(gbAWB != gblastAWB)
            gbUpdAWB = 1;

        gblastAWB = gbAWB;
        break;
    case PU_GAIN_CONTROL:
        // under coding
#if USE_CS_OUT_RANGE_CHK
        if(usb_vc_cmd_get_simple_value(&PU_GAIN_CFG, &gsGain, "PuGain")){
            return;
        }
        else{
            if(gbAE != AEC_DEF){
                //none auto mode
                USB_SetGain(PCAM_NONBLOCKING, gsGain);
            }
            dbg_printf(3, " Gain=%d, AE=%d\r\n", gsGain, gbAE);
        }
#else
        USBOutData = 0;           
        tmp2 = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        tmp2 |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;

        if((tmp2 > GAIN_MAX) || (signed) tmp2 < GAIN_MIN){
            // un-support
            UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
            gbVCERRCode = CONTROL_OUT_OF_RANGE;                    
            break;
        }
        else{
            //              UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            gsGain = tmp2;
            // to do here
            if(gbAE != AEC_DEF){
                USB_SetGain(PCAM_NONBLOCKING, gsGain);
            }
            dbg_printf(3, " Gain=%d, AE=%d\r\n", gsGain, gbAE);
        }
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
#endif
        break;
#if 0
        case PU_CONTROL_UNDEFINED:
        case PU_WHITE_BALANCE_COMPONENT_CONTROL:
        case PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
        case PU_DIGITAL_MULTIPLIER_CONTROL:
        case PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
        case PU_HUE_AUTO_CONTROL:
        case PU_ANALOG_VIDEO_STANDARD_CONTROL:
        case PU_ANALOG_LOCK_STATUS_CONTROL:
#endif
    default:
        // impossible flow
        usb_vc_stall_rx(CONTROL_INVALID_CONTROL);
        return;
        break;
    }
#if USE_CS_OUT_RANGE_CHK
    USBInPhase = SET_CUR_CMD;
    usb_ep0_null_in();
#endif
}



void usb_vc_vsi_cs_out(void)
{
    MMP_UBYTE cs;
#if USE_PUT_FUNCTION_IN_VSI == 0
    MMP_USHORT i;
    MMP_USHORT *tmpptr;
#if (USING_STILL_METHOD_1 == 0)
    MMP_UBYTE *tmpptrb;
#endif
    AITPS_USB_CTL pUSB_CTL = AITC_BASE_USBCTL;
#endif
    MMP_ULONG VcPayloadSize;

    cs = (UsbRequestPayload_wValue >> 8);

    switch(cs){
    case VS_PROBE_CONTROL:
#if USE_PUT_FUNCTION_IN_VSI
        usb_vc_get_ep0_data((MMP_UBYTE *) &vpin);
#else
        tmpptr = (MMP_USHORT *) &vpin;
        USBOutData = 0;

        for(i = 0;i < UsbRequestPayload_wLength / 2;i++){
            *(tmpptr + i) = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
            *(tmpptr + i) |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        }
#endif

        if((vpin.bFormatIndex) > TOTAL_NUM_VIDEO_FORMAT || (vpin.bFormatIndex) < 1){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RTNA_DBG_Str(0, " ** VS_PROBE_CONTROL stall\r\n"); 
            break;
        }

#if ENABLE_YUY2
        if((vpin.bFormatIndex) == YUY2_FORMAT_INDEX){
            //YUY2

            //if((vpin.wIndex >> 8) > NUM_D1_YUY2_VIDEO || (vpin.wIndex >> 8) < 1) {
            if((vpin.bFrameIndex) > NUM_D1_YUY2_VIDEO || (vpin.bFrameIndex < 1)){
                // un-support
                usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
                RTNA_DBG_Str(0, " ** VS_PROBE_CONTROL stall\r\n"); 
                break;
            }
        }
#endif

#ifdef ENABLE_UYVY
        if((vpin.wIndex & 0xFF) == UYVY_FORMAT_INDEX){
            //UYVY

            if((vpin.wIndex >> 8) > NUM_UYVY_VIDEO || (vpin.wIndex >> 8) < 1){
                // un-support
                UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
                gbVCERRCode = CONTROL_OUT_OF_RANGE;
                RTNA_DBG_Str(0, " ** VS_PROBE_CONTROL stall\r\n"); 
                break;
            }
        }
#endif

#if ENABLE_MJPEG
        if((vpin.bFormatIndex) == MJPEG_FORMAT_INDEX){
            //MJPG
#if SUPPORT_DUAL_DEVICE
            if(((UsbRequestPayload_wIndex == UVC_D1_STREAM_IF1_NO) &&
                ((vpin.bFrameIndex) > NUM_D1_MJPG_VIDEO || (vpin.bFrameIndex) < 1)) ||
               ((UsbRequestPayload_wIndex == UVC_D2_STREAM_IF1_NO) &&
                ((vpin.bFrameIndex) > NUM_D2_MJPG_VIDEO || (vpin.bFrameIndex) < 1)))
            #elif SUPPORT_SWITCH_CAMERA
                if(((gbSwitchSensor == MAIN_SENSOR) &&
                    ((vpin.bFrameIndex) > NUM_D1_MJPG_VIDEO || (vpin.bFrameIndex) < 1)) ||
                   ((gbSwitchSensor == SUB_SENSOR) &&
                    ((vpin.bFrameIndex) > NUM_D2_MJPG_VIDEO || (vpin.bFrameIndex) < 1)))
                    #else
                    //if((vpin.wIndex >> 8) > NUM_D1_MJPG_VIDEO || (vpin.wIndex >> 8) < 1)
                    if((vpin.bFrameIndex) > NUM_D1_MJPG_VIDEO || (vpin.bFrameIndex < 1))
                    #endif
                    {
                        // un-support
                        usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
                        RTNA_DBG_Str(0, " ** VS_PROBE_CONTROL stall\r\n"); 
                        break;
                    }
        }
#endif

#if BLOCK_2_UVC_INTERFACE && (BLOCK_2_UVC_INTERFACE_PROC_VER==1)
         {
            MMP_BOOL IsPreviewEnable;

            MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
            dbg_printf(0, " O VS_PROBE, IsPreviewEnable:%d\r\n", IsPreviewEnable);
            if(IsPreviewEnable){
                dbg_printf(0, "  ! Curr=%d, New=%d, _NOT_READY\r\n", gbCurrentSensor, UsbRequestPayload_wIndex);
                usb_vc_stall_rx(CONTROL_NOT_READY);
                break;
            }
        }
#endif        
        //           UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
        //framemode = vpin.wIndex >> 8;

        gbCurFormatIndex = vpin.bFormatIndex;
        gbCurFrameIndex = vpin.bFrameIndex;

#if 0
        RTNA_DBG_Str3("VS_PROBE_CONTROL:\r\n");

        RTNA_DBG_Str(0, " ** gbCurFormatIndex = "); 
        RTNA_DBG_Short(0, gbCurFormatIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
        RTNA_DBG_Str(0, " ** gbCurFrameIndex = "); 
        RTNA_DBG_Short(0, gbCurFrameIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
#endif                
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
        break;

    case VS_COMMIT_CONTROL:
#if USE_PUT_FUNCTION_IN_VSI
        usb_vc_get_ep0_data((MMP_UBYTE *) &vpin);
#else
        tmpptr = (MMP_USHORT *) &vpin;
        USBOutData = 0;           

        for(i = 0;i < UsbRequestPayload_wLength / 2;i++){
            *(tmpptr + i) = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
            *(tmpptr + i) |= pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B << 8;
        }
#endif

        //if( ((vpin.wIndex >> 8) != gbCurFrameIndex) && ((vpin.wIndex && 0xFF) != gbCurFormatIndex) )
        if(((vpin.bFrameIndex) != gbCurFrameIndex) && ((vpin.bFormatIndex) != gbCurFormatIndex)){
            usb_vc_stall_rx(CONTROL_WRONG_STATE);
            RTNA_DBG_Str(0, " ** VS_COMMIT_CONTROL stall\r\n"); 
            break;
        }
#if 0
RTNA_DBG_Short(0, vpin.wIndex); 
RTNA_DBG_Str(0, " ** vpin.wIndex\r\n"); 
#endif

#if BLOCK_2_UVC_INTERFACE && (BLOCK_2_UVC_INTERFACE_PROC_VER==2)
         {
            MMP_BOOL IsPreviewEnable;

            MMPS_3GPRECD_GetPreviewDisplay(&IsPreviewEnable);
            dbg_printf(0, " O VS_COMMIT, IsPreviewEnable:%d\r\n", IsPreviewEnable);
            if(IsPreviewEnable){
                dbg_printf(0, "  ! Curr=%d, New=%d, _NOT_READY\r\n", gbCurrentSensor, UsbRequestPayload_wIndex);
                usb_vc_stall_rx(CONTROL_NOT_READY);
                break;
            }
        }
#endif

#if XU_FRAMEBASE_CAPTURE
        if (gFramebaseCap.format == CF_YUY2/*1*/) { //EX_YUY2
            /*YUY2{720p, 480p, 240p, 120p, 90p, 180p, 360p}*/
            MMP_UBYTE FrameRes[7] = {7, 1, 3, 2, 11, 12, 4};
            gbCurFormatIndex = 1;
            gbCurH264Type = INVALID_H264;
            gbCurFrameIndex = FrameRes[vpin.bFrameIndex-1];//Mapping resolution
        } else if (gFramebaseCap.format == CF_MJPEG/*2*/) {   //EX_MJPG
            /*MJPEG{720p, 480p, 240p, 120p, 90p, 180p, 360p}*/
            MMP_UBYTE FrameRes[7] = {1, 7, 3, 2, 12, 13, 4};
            gbCurFormatIndex = 2;
            gbCurH264Type = INVALID_H264;
            gbCurFrameIndex = FrameRes[vpin.bFrameIndex-1];//Mapping resolution
        } else {    //EX_H264
            gbCurFormatIndex = vpin.bFormatIndex;
            gbCurFrameIndex = vpin.bFrameIndex;
        }
#else
        gbCurFormatIndex = vpin.bFormatIndex;
        gbCurFrameIndex = vpin.bFrameIndex;        
#endif

#if 0
        RTNA_DBG_Str3("VS_COMMIT_CONTROL:\r\n");
        
        RTNA_DBG_Str(0, " ** gbCurFormatIndex = "); 
        RTNA_DBG_Short(0, gbCurFormatIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
        RTNA_DBG_Str(0, " ** gbCurFrameIndex = "); 
        RTNA_DBG_Short(0, gbCurFrameIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
#endif                

        usb_vc_get_video_probe(gbCurFormatIndex, gbCurFrameIndex, 1);

        VcPayloadSize = vpin.dwMaxPayloadSize;
        if(VcPayloadSize != 0){
            if(VcPayloadSize > (vp.dwMaxPayloadSize))// BW over current
            {
                usb_vc_stall_rx(CONTROL_WRONG_STATE);
                RTNA_DBG_Str(0, " ** VS_COMMIT_CONTROL stall\r\n"); 
                break;
            }
            else{
#if SKYPE_MODE_B
                if(gbCurH264Type == SKYPE_H264){
#if USB_UVC_SKYPE
                    RTNA_DBG_Str3("     [H264] : Skype Mode\r\n");
                    if((gbCurFrameIndex == 1) && (gbCurFormatIndex == YUY2_FORMAT_INDEX)){
                        //gbSkypeMode = 0x01;//0x02;
                        if(gbSkypeMode == 2){
                            SetH264Mode(gbSkypeEncRes);
                        }
                        else{
                            SetH264Mode(0);
                        }
                    }
                    else{
                        gbSkypeMode = 0x01;
                        SetH264Mode(0);
                    }
#endif
                }
#else
                if(0){
                }
#endif
#if USB_MJPEGH264_STREAM
                else if(gbCurH264Type == UVC_H264){
                    RTNA_DBG_Str3("     [H264] : LGT Mode\r\n");
                    if(gbCurFormatIndex == MJPEG_FORMAT_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif                    
#if USB_FRAMEBASE_H264_ONLY
                else if(gbCurH264Type == FRAMEBASE_H264){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif
#if USB_FRAMEBASE_H264_YUY2_STREAM
                else if(gbCurH264Type == FRAMEBASE_H264_YUY2){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 + YUY2 Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif                    
#if USB_FRAMEBASE_H264_MJPEG_STREAM
                else if(gbCurH264Type == FRAMEBASE_H264RT_MJPEG){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 RT + MJPEG Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
                else if(gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 Frame + MJPEG Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif
#if USB_FRAMEBASE_DUAL_H264_STREAM
                else if(gbCurH264Type == FRAMEBASE_DUAL_H264){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 + H264 Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
                else if(gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG){
                    RTNA_DBG_Str3("     [H264] : Frame Base H264 + H264 + MJPEG Mode\r\n");
                    if(gbCurFormatIndex == FRAME_BASE_H264_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif
#if (SECS_VER > 0)
                else if(gbCurH264Type == SKYPE_TX_STREAM){
                    RTNA_DBG_Str3("     [H264] : Skype Transport Stream Mode\r\n");
                    if(gbCurFormatIndex == MJPEG_FORMAT_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif                    
#if SKYPE_UVC_H264
                else if(gbCurH264Type == UVC_H264_STREAM){
                    RTNA_DBG_Str3("     [H264] : Skype UVC H.264 Stream Mode\r\n");
                    if(gbCurFormatIndex == MJPEG_FORMAT_INDEX){
                        SetH264Mode(gbCurFrameIndex);
                    }
                    else{
                    }
                }
#endif                    
                else{
                    //#if USB_UVC_SKYPE
                    gbSkypeMode = 0x01;   
                    //#endif
                    SetH264Mode(0);
                }

                //#ifdef UVC_TEST
#if USB_UVC_BULK_EP         
                UvcSampleBuilder.initialized = 0;
                UsbTransfer.toggle = 0x00;
                gbUvcCommitted = 1;
                gbdrawflag = 0;

                //USB_LEDDisplay(LED_READY, LED_ON);

                dbg_printf(3, "LinuxProbeCheck = %d\r\n", LinuxProbeCheck);
                if(LinuxProbeCheck){
                    usb_uvc_start_preview();
                    LinuxProbeCheck = 0;
                }
                else {
                    usb_ep0_null_in();
                }
#else
                UvcSampleBuilder.initialized = 0;
                UsbTransfer.toggle = 0x00;
                gbUvcCommitted = 1;
                gbdrawflag = 0;
#endif
                //#else             
                //  xx              gbvcstart = 1;
                //                usb_vc_send_image(0); 
                //#endif            


                //RTNA_DBG_Str(0, "@-@-@\r\n"); 
#if 0     
 
                //RTNA_DBG_Str(0, " ** VcPayloadSize = "); 
                //RTNA_DBG_Short(0, VcPayloadSize);     
                //RTNA_DBG_Str(0, " **\r\n"); 
                //RTNA_DBG_Str(0, " ** packetcount = "); 
                //RTNA_DBG_Long(0, packetcount);     
                //RTNA_DBG_Str(0, " **\r\n"); 
                RTNA_DBG_Str(0, " ** frametoggle = "); 
                RTNA_DBG_Long(0, UvcSampleBuilder.toggle);
                RTNA_DBG_Str(0, " **\r\n"); 
                RTNA_DBG_Str(0, " ** gbUvcCommitted = "); 
                RTNA_DBG_Long(0, gbUvcCommitted);     
                RTNA_DBG_Str(0, " **\r\n"); 
                //                 UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
#endif
                USBInPhase = SET_CUR_CMD;
                usb_ep0_null_in();
            }
        }
        else{
            //                 UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            // move to clear feature command, tomy@2010_05_28            
            //#if USB_UVC_BULK_EP           
            //            if(gbvcstart) {
            //
            //               USB_LEDDisplay(LED_READY, LED_OFF);
            //
            //             usb_uvc_stop_preview();
            //            }
            //#endif
            USBInPhase = SET_CUR_CMD;
            usb_ep0_null_in();
        }
        break;

#if (USING_STILL_METHOD_1 == 0)
    case VS_STILL_PROBE_CONTROL:
#if USE_PUT_FUNCTION_IN_VSI
        usb_vc_get_ep0_data((MMP_UBYTE *) &spin);
#else
        tmpptrb = (MMP_UBYTE *) &spin;
        USBOutData = 0;           

        for(i = 0;i < UsbRequestPayload_wLength;i++){
            *(tmpptrb + i) = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        }
        /*
        RTNA_DBG_Str(0, " ** UsbRequestPayload_wLength = "); 
        RTNA_DBG_Short(0, UsbRequestPayload_wLength);     
        RTNA_DBG_Str(0, " **\r\n"); 
        */
#endif

        if(spin.bFormatIndex > TOTAL_NUM_VIDEO_FORMAT || spin.bFormatIndex < 1){
            // un-support
            usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
            RTNA_DBG_Str(0, " ** VS_STILL_PROBE_CONTROL stall\r\n"); 
            break;
        }


#if ENABLE_YUY2
        if(spin.bFormatIndex == YUY2_FORMAT_INDEX){
            //YUY2

            if(spin.bFrameIndex > NUM_YUY2_STILL || spin.bFrameIndex < 1){
                // un-support
                usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
                RTNA_DBG_Str(0, " ** VS_STILL_PROBE_CONTROL stall\r\n"); 
                break;
            }
        }
#endif

#ifdef ENABLE_UYVY
        if(spin.bFormatIndex == UYVY_FORMAT_INDEX){
            //UYVY

            if(spin.bFrameIndex > NUM_UYVY_STILL || spin.bFrameIndex < 1){
                // un-support
                UsbWriteEp0CSR(SET_EP0_SENDSTALL | SET_EP0_SERVICED_RXPKTRDY);
                gbVCERRCode = CONTROL_OUT_OF_RANGE;
                RTNA_DBG_Str(0, " ** VS_STILL_PROBE_CONTROL stall\r\n"); 
                break;
            }
        }
#endif

#if ENABLE_MJPEG
        if(spin.bFormatIndex == MJPEG_FORMAT_INDEX){
            //MJPG
            if(spin.bFrameIndex > NUM_MJPG_STILL || spin.bFrameIndex < 1){
                // un-support
                usb_vc_stall_rx(CONTROL_OUT_OF_RANGE);
                RTNA_DBG_Str(0, " ** VS_STILL_PROBE_CONTROL stall\r\n"); 
                break;
            }
        }
#endif

        usb_vc_set_still_probe(spin.bFormatIndex, spin.bFrameIndex);
        /*
        RTNA_DBG_Str(0, " ** sp.bFormatIndex = "); 
        RTNA_DBG_Short(0, sp.bFormatIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
        RTNA_DBG_Str(0, " ** sp.bFrameIndex = "); 
        RTNA_DBG_Short(0, sp.bFrameIndex);     
        RTNA_DBG_Str(0, " **\r\n"); 
        */
        //           UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
        gbCurStillFormatIndex = spin.bFormatIndex;
        gbCurStillFrameIndex = spin.bFrameIndex;
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();
        break;

    case VS_STILL_COMMIT_CONTROL:
#if USE_PUT_FUNCTION_IN_VSI
        usb_vc_get_ep0_data((MMP_UBYTE *) &spin);
#else
        tmpptrb = (MMP_UBYTE *) &spin;
        USBOutData = 0;           

        for(i = 0;i < UsbRequestPayload_wLength;i++){
            *(tmpptrb + i) = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B;
        }
#endif
        /*
        RTNA_DBG_Str(0, " ** UsbRequestPayload_wLength = "); 
        RTNA_DBG_Short(0, UsbRequestPayload_wLength);     
        RTNA_DBG_Str(0, " **\r\n"); 
        */
        if(spin.bFrameIndex != gbCurStillFrameIndex) // wrong frame mode
        {
            usb_vc_stall_rx(CONTROL_WRONG_STATE);
            RTNA_DBG_Str(0, " ** VS_STILL_COMMIT_CONTROL stall\r\n"); 
            break;
        }

        VcPayloadSize = (MMP_ULONG) (spin.dwMaxPayloadSize);
        if(VcPayloadSize != 0){
            if(VcPayloadSize > sp.dwMaxPayloadSize)// BW over current
            {
                usb_vc_stall_rx(CONTROL_WRONG_STATE);
                RTNA_DBG_Str(0, " ** VS_STILL_COMMIT_CONTROL stall\r\n"); 
                break;
            }
            else{
                /*
                RTNA_DBG_Str(0, " ** VcPayloadSize = "); 
                RTNA_DBG_Short(0, VcPayloadSize);     
                RTNA_DBG_Str(0, " **\r\n"); 
                */
                usb_vc_set_still_commit(&spin);
                /*
                RTNA_DBG_Str(0, " ** sc.bFormatIndex = "); 
                RTNA_DBG_Short(0, sc.bFormatIndex);     
                RTNA_DBG_Str(0, " **\r\n"); 
                RTNA_DBG_Str(0, " ** sc.bFrameIndex = "); 
                RTNA_DBG_Short(0, sc.bFrameIndex);     
                RTNA_DBG_Str(0, " **\r\n"); 
                */
                //                UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
                USBInPhase = SET_CUR_CMD;
                usb_ep0_null_in();
            }
        }
        else{
            //                 UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
            USBInPhase = SET_CUR_CMD;
            usb_ep0_null_in();
        }
        break;

    case VS_STILL_IMAGE_TRIGGER_CONTROL:
#if USE_PUT_FUNCTION_IN_VSI
        usb_vc_get_ep0_data((MMP_UBYTE *) &gbTriOP);
#else
        USBOutData = 0;           
        gbTriOP = pUSB_CTL->USB_FIFO_EP[0x0].FIFO_B; 
#endif

        //                 UsbWriteEp0CSR(SET_EP0_SERVICED_RXPKTRDY);
        USBInPhase = SET_CUR_CMD;
        usb_ep0_null_in();  

        //usb_vc_preview_disable();

        // sti-image
        //usb_vc_send_image(1); 
        //           EnableDMA();
        //           IBC_Enable();
        /*
            gbUvcCommitted = 0;
              USB_REG_BASE_B[USB_DMA_INTSTS_B] = 0;
              gbstistart = 1;          
              */
        gbStillCaptureEvent = STILL_IMAGE_TRIGGER;
#if CAPTURE_RAW_XU
        gRawFormat = RAW_CAPTURE_BAY10;
#endif

        break;
#endif

#if 0
    case VS_CONTROL_UNDEFINED:
    case VS_STREAM_ERROR_CODE_CONTROL:
    case VS_GENERATE_KEY_FRAME_CONTROL:
    case VS_UPDATE_FRAME_SEGMENT_CONTROL:
    case VS_SYNCH_DELAY_CONTROL:
#endif
    default:
        // impossible flow       
        break;
    }
}


void usb_vc_out_data(void)
{
    MMP_UBYTE id;

    id = (UsbRequestPayload_wIndex >> 8);

    //RTNA_DBG_Str3("ID : "); RTNA_DBG_Byte3(id); RTNA_DBG_Str3("\r\n");
    if(id == 0x00){
        if((UsbRequestPayload_wIndex & 0xFF) == UVC_D1_STREAM_IF1_NO){
            usb_vc_vsi_cs_out();
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D1_CTL_IF_NO){
            usb_vc_vci_cs_out();
#if (SUPPORT_DUAL_DEVICE||SUPPORT_SWITCH_CAMERA)
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D2_STREAM_IF1_NO){
            usb_vc_vsi_cs_out();
        }
        else if((UsbRequestPayload_wIndex & 0xFF) == UVC_D2_CTL_IF_NO){
            usb_vc_vci_cs_out();
#endif
        }
        else{
            usb_vc_stall_rx(CONTROL_INVALID_UNIT);
        }
    }
    else if(id == UVC_IT_ID){
        usb_vc_ct_cs_out();
    }
#if 0     
    else if(id == gbVCOTID) 
    {
    }
    else if(id == gbVCSUID) {
        usb_vc_su_cs_out();
    }
#endif     
    else if(id == UVC_PU_ID){
        usb_vc_pu_cs_out();
    }
#if (SECS_VER > 0)
    else if(id == gbVCEU0ID){
        usb_vc_eu0_cs_out();
    }
#endif
#if SKYPE_UVC_H264
    else if(id == gbVCEU3ID){
        usb_vc_eu3_cs_out();
    }
#endif
    else if(id == gbVCEU1ID){
        usb_vc_eu1_cs_out();
    }
    else if(id == gbVCEU2ID){
        usb_vc_eu2_cs_out();
    }
    else{
        usb_vc_stall_rx(CONTROL_INVALID_UNIT);
    }
}

#endif

